package roomescape.reservation.infrastructure.persistence import org.springframework.data.jpa.domain.Specification import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.theme.infrastructure.persistence.ThemeEntity import java.time.LocalDate class ReservationSearchSpecification( private var spec: Specification = Specification { _, _, _ -> null } ) { fun sameThemeId(themeId: Long?): ReservationSearchSpecification = andIfNotNull(themeId?.let { Specification { root, _, cb -> cb.equal(root.get("theme").get("id"), themeId) } }) fun sameMemberId(memberId: Long?): ReservationSearchSpecification = andIfNotNull(memberId?.let { Specification { root, _, cb -> cb.equal(root.get("member").get("id"), memberId) } }) fun sameTimeId(timeId: Long?): ReservationSearchSpecification = andIfNotNull(timeId?.let { Specification { root, _, cb -> cb.equal(root.get("time").get("id"), timeId) } }) fun sameDate(date: LocalDate?): ReservationSearchSpecification = andIfNotNull(date?.let { Specification { root, _, cb -> cb.equal(root.get("date"), date) } }) fun confirmed(): ReservationSearchSpecification = andIfNotNull { root, _, cb -> cb.or( cb.equal( root.get("reservationStatus"), ReservationStatus.CONFIRMED ), cb.equal( root.get("reservationStatus"), ReservationStatus.CONFIRMED_PAYMENT_REQUIRED ) ) } fun waiting(): ReservationSearchSpecification = andIfNotNull { root, _, cb -> cb.equal( root.get("reservationStatus"), ReservationStatus.WAITING ) } fun dateStartFrom(dateFrom: LocalDate?): ReservationSearchSpecification = andIfNotNull(dateFrom?.let { Specification { root, _, cb -> cb.greaterThanOrEqualTo(root.get("date"), dateFrom) } }) fun dateEndAt(dateTo: LocalDate?): ReservationSearchSpecification = andIfNotNull(dateTo?.let { Specification { root, _, cb -> cb.lessThanOrEqualTo(root.get("date"), dateTo) } }) fun build(): Specification { return this.spec } private fun andIfNotNull(condition: Specification?): ReservationSearchSpecification { condition?.let { this.spec = this.spec.and(condition) } return this } }