package roomescape.reservation.business 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 import java.time.LocalTime @Service 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 ) @Transactional(readOnly = true) fun findAllTimes(): ReservationTimesResponse = reservationTimeRepository.findAll() .toResponses() @Transactional fun addTime(reservationTimeRequest: ReservationTimeRequest): ReservationTimeResponse { val startAt: LocalTime = reservationTimeRequest.startAt if (reservationTimeRepository.existsByStartAt(startAt)) { throw RoomescapeException( ErrorType.TIME_DUPLICATED, "[startAt: $startAt]", HttpStatus.CONFLICT ) } return ReservationTimeEntity(startAt = startAt) .also { reservationTimeRepository.save(it) } .toResponse() } @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) } } @Transactional(readOnly = true) fun findAllAvailableTimesByDateAndTheme(date: LocalDate, themeId: Long): ReservationTimeInfosResponse { val allTimes = reservationTimeRepository.findAll() val reservations: List = reservationRepository.findByDateAndThemeId(date, themeId) return ReservationTimeInfosResponse(allTimes.map { time -> val alreadyBooked: Boolean = reservations.any { reservation -> reservation.reservationTime.id == time.id } time.toInfoResponse(alreadyBooked) }) } }