package roomescape.time.business import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationRepository import roomescape.time.exception.TimeErrorCode import roomescape.time.exception.TimeException import roomescape.time.infrastructure.persistence.TimeEntity import roomescape.time.infrastructure.persistence.TimeRepository import roomescape.time.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 TimeException(TimeErrorCode.TIME_NOT_FOUND) @Transactional(readOnly = true) fun findTimes(): TimeRetrieveListResponse = timeRepository.findAll() .toResponse() @Transactional fun createTime(request: TimeCreateRequest): TimeCreateResponse { val startAt: LocalTime = request.startAt if (timeRepository.existsByStartAt(startAt)) { throw TimeException(TimeErrorCode.TIME_DUPLICATED) } val time: TimeEntity = request.toEntity() return timeRepository.save(time).toCreateResponse() } @Transactional fun deleteTime(id: Long) { val time: TimeEntity = findById(id) val reservations: List = reservationRepository.findAllByTime(time) if (reservations.isNotEmpty()) { throw TimeException(TimeErrorCode.TIME_ALREADY_RESERVED) } timeRepository.delete(time) } @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) }) } }