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.TimeEntity import roomescape.reservation.infrastructure.persistence.TimeRepository import roomescape.reservation.web.* import java.time.LocalDate import java.time.LocalTime @Service class TimeService( private val timeRepository: TimeRepository, private val reservationRepository: ReservationRepository ) { @Transactional(readOnly = true) fun findById(id: Long): TimeEntity = timeRepository.findByIdOrNull(id) ?: throw RoomescapeException( ErrorType.TIME_NOT_FOUND, "[timeId: $id]", HttpStatus.BAD_REQUEST ) @Transactional(readOnly = true) fun findTimes(): TimeRetrieveListResponse = timeRepository.findAll().toRetrieveListResponse() @Transactional fun createTime(timeCreateRequest: TimeCreateRequest): TimeCreateResponse { val startAt: LocalTime = timeCreateRequest.startAt if (timeRepository.existsByStartAt(startAt)) { throw RoomescapeException( ErrorType.TIME_DUPLICATED, "[startAt: $startAt]", HttpStatus.CONFLICT ) } return TimeEntity(startAt = startAt) .also { timeRepository.save(it) } .toCreateResponse() } @Transactional fun deleteTime(id: Long) { val time: TimeEntity = findById(id) reservationRepository.findByTime(time) .also { if (it.isNotEmpty()) { throw RoomescapeException( ErrorType.TIME_IS_USED_CONFLICT, "[timeId: $id]", HttpStatus.CONFLICT ) } timeRepository.deleteById(id) } } @Transactional(readOnly = true) fun findTimesWithAvailability(date: LocalDate, themeId: Long): TimeWithAvailabilityListResponse { val allTimes = timeRepository.findAll() val reservations: List = reservationRepository.findByDateAndThemeId(date, themeId) return TimeWithAvailabilityListResponse(allTimes.map { time -> val isAvailable: Boolean = reservations.none { reservation -> reservation.time.id == time.id } TimeWithAvailabilityResponse(time.id!!, time.startAt, isAvailable) }) } }