From 768c47f1aef86c01bfc753ea6218612b2e7cac8d Mon Sep 17 00:00:00 2001 From: pricelees Date: Tue, 14 Oct 2025 09:48:59 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EA=B2=B0=EC=A0=9C=20&=20=EC=98=88?= =?UTF-8?q?=EC=95=BD=20=ED=99=95=EC=A0=95=20=EB=A1=9C=EC=A7=81=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EA=B2=80=EC=A6=9D=20=EA=B3=BC=EC=A0=95=EC=9D=84=20?= =?UTF-8?q?=EB=91=90=20=EA=B0=9C=EC=9D=98=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20->=20=ED=95=98=EB=82=98=EC=9D=98=20=ED=8A=B8?= =?UTF-8?q?=EB=9E=9C=EC=9E=AD=EC=85=98=EC=9C=BC=EB=A1=9C=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9=20=EB=B0=8F=20=EC=BF=BC=EB=A6=AC=20=EC=88=9C=EC=84=9C?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/order/business/OrderService.kt | 30 ++++++++++++++----- .../order/business/OrderValidator.kt | 9 +----- .../persistence/PaymentAttemptRepository.kt | 2 ++ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderService.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderService.kt index 1662d322..76a9dcdc 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderService.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderService.kt @@ -36,14 +36,18 @@ class OrderService( ) { fun confirm(reservationId: Long, paymentConfirmRequest: PaymentConfirmRequest) { - val trial = paymentAttemptRepository.countByReservationId(reservationId) + var trial: Long = 0 val paymentKey = paymentConfirmRequest.paymentKey log.info { "[confirm] 결제 및 예약 확정 시작: reservationId=${reservationId}, paymentKey=${paymentKey}" } - try { - transactionExecutionUtil.withNewTransaction(isReadOnly = false) { - validateAndMarkInProgress(reservationId) + trial = transactionExecutionUtil.withNewTransaction(isReadOnly = false) { + getTrialAfterValidateCanConfirm(reservationId).also { + reservationService.markInProgress(reservationId) + } + } ?: run { + log.warn { "[confirm] 모든 paymentAttempts 조회 과정에서의 예상치 못한 null 응답: reservationId=${reservationId}" } + throw OrderException(OrderErrorCode.BOOKING_UNEXPECTED_ERROR) } val paymentClientResponse: PaymentGatewayResponse = @@ -61,20 +65,32 @@ class OrderService( } } - private fun validateAndMarkInProgress(reservationId: Long) { + private fun getTrialAfterValidateCanConfirm(reservationId: Long): Long { log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 시작: reservationId=${reservationId}" } val reservation: ReservationStateResponse = reservationService.findStatusWithLock(reservationId) val schedule: ScheduleStateResponse = scheduleService.findStateWithLock(reservation.scheduleId) try { orderValidator.validateCanConfirm(reservation, schedule) - log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 완료: reservationId=${reservationId}" } + + return getTrialIfSuccessAttemptNotExists(reservationId).also { + log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 완료: reservationId=${reservationId}" } + } } catch (e: OrderException) { val errorCode = OrderErrorCode.NOT_CONFIRMABLE throw OrderException(errorCode, e.message) } + } - reservationService.markInProgress(reservationId) + private fun getTrialIfSuccessAttemptNotExists(reservationId: Long): Long { + val paymentAttempts: List = paymentAttemptRepository.findAllByReservationId(reservationId) + + if (paymentAttempts.any { it.result == AttemptResult.SUCCESS }) { + log.info { "[validateCanConfirm] 이미 결제 완료된 예약: id=${reservationId}" } + throw OrderException(OrderErrorCode.BOOKING_ALREADY_COMPLETED) + } + + return paymentAttempts.size.toLong() } private fun requestConfirmPayment( diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderValidator.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderValidator.kt index 8ee18671..7be57c88 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderValidator.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/business/OrderValidator.kt @@ -16,18 +16,11 @@ import java.time.LocalDateTime private val log: KLogger = KotlinLogging.logger {} @Component -class OrderValidator( - private val paymentAttemptRepository: PaymentAttemptRepository -) { +class OrderValidator { fun validateCanConfirm( reservation: ReservationStateResponse, schedule: ScheduleStateResponse ) { - if (paymentAttemptRepository.isSuccessAttemptExists(reservation.id)) { - log.info { "[validateCanConfirm] 이미 결제 완료된 예약: id=${reservation.id}" } - throw OrderException(OrderErrorCode.BOOKING_ALREADY_COMPLETED) - } - validateReservationStatus(reservation) validateScheduleStatus(schedule) } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/infrastructure/persistence/PaymentAttemptRepository.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/infrastructure/persistence/PaymentAttemptRepository.kt index 3c5e8666..4f2ff58f 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/order/infrastructure/persistence/PaymentAttemptRepository.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/infrastructure/persistence/PaymentAttemptRepository.kt @@ -23,4 +23,6 @@ interface PaymentAttemptRepository: JpaRepository { """ ) fun isSuccessAttemptExists(reservationId: Long): Boolean + + fun findAllByReservationId(reservationId: Long): List }