generated from pricelees/issue-pr-template
<!-- 제목 양식 --> <!-- [이슈번호] 작업 요약 (예시: [#10] Gitea 템플릿 생성) --> ## 📝 관련 이슈 및 PR **PR과 관련된 이슈 번호** - #30 ## ✨ 작업 내용 <!-- 어떤 작업을 했는지 알려주세요! --> - ReservationService를 읽기(Find) / 쓰기(Write) 서비스로 분리 - 모든 도메인에 repository를 사용하는 Finder, Writer, Validator 도입 -> ReservationService에 있는 조회, 검증, 쓰기 작업을 별도의 클래스로 분리하기 위함이었고, 이 과정에서 다른 도메인에도 도입함. ## 🧪 테스트 <!-- 어떤 테스트를 생각했고 진행했는지 알려주세요! --> 새로 추가된 기능 & 클래스는 모두 테스트 추가하였고, 작업 후 전체 테스트 완료 ## 📚 참고 자료 및 기타 <!-- 참고한 자료, 또는 논의할 사항이 있다면 알려주세요! --> Reviewed-on: #31 Co-authored-by: pricelees <priceelees@gmail.com> Co-committed-by: pricelees <priceelees@gmail.com>
95 lines
4.1 KiB
Kotlin
95 lines
4.1 KiB
Kotlin
package roomescape.reservation.implement
|
|
|
|
import io.github.oshai.kotlinlogging.KLogger
|
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
|
import org.springframework.data.jpa.domain.Specification
|
|
import org.springframework.data.repository.findByIdOrNull
|
|
import org.springframework.stereotype.Component
|
|
import roomescape.reservation.exception.ReservationErrorCode
|
|
import roomescape.reservation.exception.ReservationException
|
|
import roomescape.reservation.infrastructure.persistence.ReservationEntity
|
|
import roomescape.reservation.infrastructure.persistence.ReservationRepository
|
|
import roomescape.reservation.infrastructure.persistence.ReservationSearchSpecification
|
|
import roomescape.reservation.infrastructure.persistence.ReservationStatus
|
|
import roomescape.reservation.web.MyReservationRetrieveResponse
|
|
import roomescape.theme.infrastructure.persistence.ThemeEntity
|
|
import roomescape.time.infrastructure.persistence.TimeEntity
|
|
import java.time.LocalDate
|
|
|
|
private val log: KLogger = KotlinLogging.logger {}
|
|
|
|
@Component
|
|
class ReservationFinder(
|
|
private val reservationRepository: ReservationRepository,
|
|
private val reservationValidator: ReservationValidator,
|
|
) {
|
|
fun findById(id: Long): ReservationEntity {
|
|
log.debug { "[ReservationFinder.findById] 시작: id=$id" }
|
|
|
|
return reservationRepository.findByIdOrNull(id)
|
|
?.also { log.debug { "[ReservationFinder.findById] 완료: reservationId=$id, date:${it.date}, timeId:${it.time.id}, themeId:${it.theme.id}" } }
|
|
?: run {
|
|
log.warn { "[ReservationFinder.findById] 조회 실패: reservationId=$id" }
|
|
throw ReservationException(ReservationErrorCode.RESERVATION_NOT_FOUND)
|
|
}
|
|
}
|
|
|
|
fun findAllByStatuses(vararg statuses: ReservationStatus): List<ReservationEntity> {
|
|
log.debug { "[ReservationFinder.findAll] 시작: status=${statuses}" }
|
|
|
|
val spec = ReservationSearchSpecification()
|
|
.status(*statuses)
|
|
.build()
|
|
|
|
return reservationRepository.findAll(spec)
|
|
.also { log.debug { "[ReservationFinder.findAll] ${it.size}개 예약 조회 완료: status=${statuses}" } }
|
|
}
|
|
|
|
fun findAllByDateAndTheme(
|
|
date: LocalDate, theme: ThemeEntity
|
|
): List<ReservationEntity> {
|
|
log.debug { "[ReservationFinder.findAllByDateAndTheme] 시작: date=$date, themeId=${theme.id}" }
|
|
|
|
return reservationRepository.findAllByDateAndTheme(date, theme)
|
|
.also { log.debug { "[ReservationFinder.findAllByDateAndTheme] ${it.size}개 조회 완료: date=$date, themeId=${theme.id}" } }
|
|
}
|
|
|
|
fun findAllByMemberId(memberId: Long): List<MyReservationRetrieveResponse> {
|
|
log.debug { "[ReservationFinder.findAllByMemberId] 시작: memberId=${memberId}" }
|
|
|
|
return reservationRepository.findAllByMemberId(memberId)
|
|
.also { log.debug { "[ReservationFinder.findAllByMemberId] ${it.size}개 예약(대기) 조회 완료: memberId=${memberId}" } }
|
|
}
|
|
|
|
fun searchReservations(
|
|
themeId: Long?,
|
|
memberId: Long?,
|
|
startFrom: LocalDate?,
|
|
endAt: LocalDate?,
|
|
): List<ReservationEntity> {
|
|
reservationValidator.validateSearchDateRange(startFrom, endAt)
|
|
|
|
val spec: Specification<ReservationEntity> = ReservationSearchSpecification()
|
|
.sameThemeId(themeId)
|
|
.sameMemberId(memberId)
|
|
.dateStartFrom(startFrom)
|
|
.dateEndAt(endAt)
|
|
.status(ReservationStatus.CONFIRMED, ReservationStatus.CONFIRMED_PAYMENT_REQUIRED)
|
|
.build()
|
|
|
|
return reservationRepository.findAll(spec)
|
|
.also {
|
|
log.debug { "[ReservationFinder.searchReservations] ${it.size}개 예약 조회 완료. " +
|
|
"themeId=${themeId}, memberId=${memberId}, startFrom=${startFrom}, endAt=${endAt}" }
|
|
}
|
|
|
|
}
|
|
|
|
fun isTimeReserved(time: TimeEntity): Boolean {
|
|
log.debug { "[ReservationFinder.isTimeReserved] 시작: timeId=${time.id}, startAt=${time.startAt}" }
|
|
|
|
return reservationRepository.existsByTime(time)
|
|
.also { log.debug { "[ReservationFinder.isTimeReserved] 완료: isExist=$it, timeId=${time.id}, startAt=${time.startAt}" } }
|
|
}
|
|
}
|