From a83352c73342acee40426e0770320ea75e33db57 Mon Sep 17 00:00:00 2001 From: pricelees Date: Thu, 16 Oct 2025 15:28:56 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20OrderService=EC=9D=98=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=20&=20=EC=98=88=EC=95=BD=20=ED=99=95=EC=A0=95=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=97=90=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomescape/order/business/OrderService.kt | 101 +++--------------- .../order/business/OrderValidator.kt | 3 +- .../order/exception/OrderErrorCode.kt | 4 +- .../order/exception/OrderException.kt | 7 -- 4 files changed, 15 insertions(+), 100 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 76a9dcdc..e77703f6 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 @@ -1,146 +1,69 @@ package com.sangdol.roomescape.order.business -import com.sangdol.common.persistence.IDGenerator import com.sangdol.common.persistence.TransactionExecutionUtil import com.sangdol.common.types.exception.ErrorCode import com.sangdol.common.types.exception.RoomescapeException import com.sangdol.roomescape.order.exception.OrderErrorCode import com.sangdol.roomescape.order.exception.OrderException -import com.sangdol.roomescape.order.infrastructure.persistence.AttemptResult -import com.sangdol.roomescape.order.infrastructure.persistence.PaymentAttemptEntity -import com.sangdol.roomescape.order.infrastructure.persistence.PaymentAttemptRepository import com.sangdol.roomescape.payment.business.PaymentService import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest -import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse -import com.sangdol.roomescape.payment.exception.PaymentException import com.sangdol.roomescape.reservation.business.ReservationService +import com.sangdol.roomescape.reservation.business.event.ReservationConfirmEvent import com.sangdol.roomescape.reservation.dto.ReservationStateResponse import com.sangdol.roomescape.schedule.business.ScheduleService import com.sangdol.roomescape.schedule.dto.ScheduleStateResponse import io.github.oshai.kotlinlogging.KLogger import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service private val log: KLogger = KotlinLogging.logger {} @Service class OrderService( - private val idGenerator: IDGenerator, private val reservationService: ReservationService, private val scheduleService: ScheduleService, private val paymentService: PaymentService, private val transactionExecutionUtil: TransactionExecutionUtil, private val orderValidator: OrderValidator, - private val paymentAttemptRepository: PaymentAttemptRepository, - private val orderPostProcessorService: OrderPostProcessorService + private val eventPublisher: ApplicationEventPublisher ) { fun confirm(reservationId: Long, paymentConfirmRequest: PaymentConfirmRequest) { - var trial: Long = 0 val paymentKey = paymentConfirmRequest.paymentKey log.info { "[confirm] 결제 및 예약 확정 시작: reservationId=${reservationId}, paymentKey=${paymentKey}" } try { - 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) + transactionExecutionUtil.withNewTransaction(isReadOnly = false) { + validateCanConfirm(reservationId) + reservationService.markInProgress(reservationId) } - val paymentClientResponse: PaymentGatewayResponse = - requestConfirmPayment(reservationId, paymentConfirmRequest) + paymentService.requestConfirm(reservationId, paymentConfirmRequest) + eventPublisher.publishEvent(ReservationConfirmEvent(reservationId)) - orderPostProcessorService.processAfterPaymentConfirmation(reservationId, paymentClientResponse) + log.info { "[confirm] 결제 처리 및 예약 확정 이벤트 발행 완료" } } catch (e: Exception) { val errorCode: ErrorCode = if (e is RoomescapeException) { e.errorCode } else { - OrderErrorCode.BOOKING_UNEXPECTED_ERROR + OrderErrorCode.ORDER_UNEXPECTED_ERROR } - throw OrderException(errorCode, e.message ?: errorCode.message, trial) + throw OrderException(errorCode, e.message ?: errorCode.message) } } - private fun getTrialAfterValidateCanConfirm(reservationId: Long): Long { + private fun validateCanConfirm(reservationId: Long) { log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 시작: reservationId=${reservationId}" } val reservation: ReservationStateResponse = reservationService.findStatusWithLock(reservationId) val schedule: ScheduleStateResponse = scheduleService.findStateWithLock(reservation.scheduleId) try { orderValidator.validateCanConfirm(reservation, schedule) - - return getTrialIfSuccessAttemptNotExists(reservationId).also { - log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 완료: reservationId=${reservationId}" } - } } catch (e: OrderException) { val errorCode = OrderErrorCode.NOT_CONFIRMABLE throw OrderException(errorCode, e.message) } } - - 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( - reservationId: Long, - paymentConfirmRequest: PaymentConfirmRequest - ): PaymentGatewayResponse { - log.info { "[requestConfirmPayment] 결제 및 이력 저장 시작: reservationId=${reservationId}, paymentKey=${paymentConfirmRequest.paymentKey}" } - val paymentResponse: PaymentGatewayResponse - var attempt: PaymentAttemptEntity? = null - - try { - paymentResponse = paymentService.requestConfirm(paymentConfirmRequest) - - attempt = PaymentAttemptEntity( - id = idGenerator.create(), - reservationId = reservationId, - result = AttemptResult.SUCCESS, - ) - } catch (e: Exception) { - val errorCode: String = if (e is PaymentException) { - log.info { "[requestConfirmPayment] 결제 요청 실패: reservationId=${reservationId}, paymentKey=${paymentConfirmRequest.paymentKey}" } - e.errorCode.name - } else { - log.warn { - "[requestConfirmPayment] 결제 요청 실패: reservationId=${reservationId}, paymentKey=${paymentConfirmRequest.paymentKey}" - } - OrderErrorCode.BOOKING_UNEXPECTED_ERROR.name - } - - attempt = PaymentAttemptEntity( - id = idGenerator.create(), - reservationId = reservationId, - result = AttemptResult.FAILED, - errorCode = errorCode, - message = e.message - ) - - throw e - } finally { - val savedAttempt: PaymentAttemptEntity? = attempt?.let { - log.info { "[requestPayment] 결제 요청 이력 저장 시작: id=${it.id}, reservationId=${it.reservationId}, result=${it.result}, errorCode=${it.errorCode}, message=${it.message}" } - paymentAttemptRepository.save(it) - } - savedAttempt?.also { - log.info { "[requestPayment] 결제 요청 이력 저장 완료: id=${savedAttempt.id}" } - } ?: run { - log.info { "[requestPayment] 결제 요청 이력 저장 실패: reservationId=${reservationId}" } - } - } - - return paymentResponse - } } 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 7be57c88..b2d724b8 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 @@ -3,7 +3,6 @@ package com.sangdol.roomescape.order.business import com.sangdol.common.utils.KoreaDateTime import com.sangdol.roomescape.order.exception.OrderErrorCode import com.sangdol.roomescape.order.exception.OrderException -import com.sangdol.roomescape.order.infrastructure.persistence.PaymentAttemptRepository import com.sangdol.roomescape.reservation.dto.ReservationStateResponse import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus import com.sangdol.roomescape.schedule.dto.ScheduleStateResponse @@ -29,7 +28,7 @@ class OrderValidator { when (reservation.status) { ReservationStatus.CONFIRMED -> { log.info { "[validateCanConfirm] 이미 확정된 예약: id=${reservation.id}" } - throw OrderException(OrderErrorCode.BOOKING_ALREADY_COMPLETED) + throw OrderException(OrderErrorCode.ORDER_ALREADY_CONFIRMED) } ReservationStatus.EXPIRED -> { log.info { "[validateCanConfirm] 만료된 예약: id=${reservation.id}" } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderErrorCode.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderErrorCode.kt index 4ed09f47..7bc94cc4 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderErrorCode.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderErrorCode.kt @@ -9,11 +9,11 @@ enum class OrderErrorCode( override val message: String ) : ErrorCode { NOT_CONFIRMABLE(HttpStatus.CONFLICT, "B000", "예약을 확정할 수 없어요."), - BOOKING_ALREADY_COMPLETED(HttpStatus.CONFLICT, "B001", "이미 완료된 예약이에요."), + ORDER_ALREADY_CONFIRMED(HttpStatus.CONFLICT, "B001", "이미 완료된 예약이에요."), EXPIRED_RESERVATION(HttpStatus.CONFLICT, "B002", "결제 가능 시간이 지나 만료된 예약이에요. 처음부터 다시 시도해주세요."), CANCELED_RESERVATION(HttpStatus.CONFLICT, "B003", "이미 취소된 예약이에요. 본인이 취소하지 않았다면 매장에 문의해주세요."), PAST_SCHEDULE(HttpStatus.CONFLICT, "B004", "지난 일정은 예약할 수 없어요."), - BOOKING_UNEXPECTED_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "B999", "예상치 못한 예외가 발생했어요. 잠시 후 다시 시도해주세요.") + ORDER_UNEXPECTED_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "B999", "예상치 못한 예외가 발생했어요. 잠시 후 다시 시도해주세요.") ; } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderException.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderException.kt index 2306f9d4..42b8b60e 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderException.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderException.kt @@ -6,11 +6,4 @@ import com.sangdol.common.types.exception.RoomescapeException class OrderException( override val errorCode: ErrorCode, override val message: String = errorCode.message, - var trial: Long = 0 ) : RoomescapeException(errorCode, message) - -class OrderErrorResponse( - val code: String, - val message: String, - val trial: Long -)