generated from pricelees/issue-pr-template
feat: 예약 확정 EventListener 및 테스트
This commit is contained in:
parent
cce59e522e
commit
66bf68826b
@ -0,0 +1,34 @@
|
||||
package com.sangdol.roomescape.reservation.business.event
|
||||
|
||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import io.github.oshai.kotlinlogging.KLogger
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import org.springframework.context.event.EventListener
|
||||
import org.springframework.scheduling.annotation.Async
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.time.Instant
|
||||
|
||||
private val log: KLogger = KotlinLogging.logger {}
|
||||
|
||||
@Component
|
||||
class ReservationEventListener(
|
||||
private val reservationRepository: ReservationRepository
|
||||
) {
|
||||
|
||||
@Async
|
||||
@EventListener
|
||||
@Transactional
|
||||
fun handleReservationConfirmEvent(event: ReservationConfirmEvent) {
|
||||
val reservationId = event.reservationId
|
||||
|
||||
log.info { "[handleReservationConfirmEvent] 예약 확정 이벤트 수신: reservationId=${reservationId}" }
|
||||
val modifiedRows = reservationRepository.confirmReservation(Instant.now(), reservationId)
|
||||
|
||||
if (modifiedRows == 0) {
|
||||
log.warn { "[handleReservationConfirmEvent] 예상치 못한 예약 확정 실패 - 변경된 row 없음: reservationId=${reservationId}" }
|
||||
}
|
||||
|
||||
log.info { "[handleReservationConfirmEvent] 예약 확정 이벤트 처리 완료" }
|
||||
}
|
||||
}
|
||||
@ -48,4 +48,23 @@ interface ReservationRepository : JpaRepository<ReservationEntity, Long> {
|
||||
""", nativeQuery = true
|
||||
)
|
||||
fun expirePendingReservations(@Param("now") now: Instant, @Param("reservationIds") reservationIds: List<Long>): Int
|
||||
|
||||
@Modifying
|
||||
@Query(
|
||||
"""
|
||||
UPDATE
|
||||
reservation r
|
||||
JOIN
|
||||
schedule s ON r.schedule_id = s.id AND s.status = 'HOLD'
|
||||
SET
|
||||
r.status = 'CONFIRMED',
|
||||
r.updated_at = :now,
|
||||
s.status = 'RESERVED',
|
||||
s.hold_expired_at = NULL
|
||||
WHERE
|
||||
r.id = :id
|
||||
AND r.status = 'PAYMENT_IN_PROGRESS'
|
||||
""", nativeQuery = true
|
||||
)
|
||||
fun confirmReservation(@Param("now") now: Instant, @Param("id") id: Long): Int
|
||||
}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
package com.sangdol.roomescape.reservation.business.event
|
||||
|
||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus
|
||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus
|
||||
import com.sangdol.roomescape.supports.FunSpecSpringbootTest
|
||||
import io.kotest.assertions.assertSoftly
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.nulls.shouldNotBeNull
|
||||
import io.kotest.matchers.shouldBe
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
|
||||
class ReservationEventListenerTest(
|
||||
private val reservationEventListener: ReservationEventListener,
|
||||
private val reservationRepository: ReservationRepository,
|
||||
private val scheduleRepository: ScheduleRepository
|
||||
) : FunSpecSpringbootTest() {
|
||||
|
||||
init {
|
||||
test("예약 확정 이벤트를 처리한다.") {
|
||||
val pendingReservation = dummyInitializer.createPendingReservation(testAuthUtil.defaultUser()).also {
|
||||
it.status = ReservationStatus.PAYMENT_IN_PROGRESS
|
||||
reservationRepository.saveAndFlush(it)
|
||||
}
|
||||
|
||||
val reservationConfirmEvent = ReservationConfirmEvent(pendingReservation.id)
|
||||
|
||||
reservationEventListener.handleReservationConfirmEvent(reservationConfirmEvent).also {
|
||||
Thread.sleep(100)
|
||||
}
|
||||
|
||||
assertSoftly(reservationRepository.findByIdOrNull(pendingReservation.id)) {
|
||||
this.shouldNotBeNull()
|
||||
this.status shouldBe ReservationStatus.CONFIRMED
|
||||
}
|
||||
|
||||
assertSoftly(scheduleRepository.findByIdOrNull(pendingReservation.scheduleId)) {
|
||||
this.shouldNotBeNull()
|
||||
this.status shouldBe ScheduleStatus.RESERVED
|
||||
this.holdExpiredAt shouldBe null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user