generated from pricelees/issue-pr-template
[#20] 도메인별 예외 분리 #21
@ -1,10 +1,9 @@
|
||||
package roomescape.payment.business
|
||||
|
||||
import org.springframework.http.HttpStatus
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import roomescape.common.exception.ErrorType
|
||||
import roomescape.common.exception.RoomescapeException
|
||||
import roomescape.payment.exception.PaymentErrorCode
|
||||
import roomescape.payment.exception.PaymentException
|
||||
import roomescape.payment.infrastructure.client.PaymentApproveResponse
|
||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity
|
||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
||||
@ -24,44 +23,45 @@ class PaymentService(
|
||||
) {
|
||||
@Transactional
|
||||
fun createPayment(
|
||||
paymentResponse: PaymentApproveResponse,
|
||||
approveResponse: PaymentApproveResponse,
|
||||
reservation: ReservationEntity
|
||||
): PaymentCreateResponse = PaymentEntity(
|
||||
orderId = paymentResponse.orderId,
|
||||
paymentKey = paymentResponse.paymentKey,
|
||||
totalAmount = paymentResponse.totalAmount,
|
||||
reservation = reservation,
|
||||
approvedAt = paymentResponse.approvedAt
|
||||
).also {
|
||||
paymentRepository.save(it)
|
||||
}.toCreateResponse()
|
||||
): PaymentCreateResponse {
|
||||
val payment = PaymentEntity(
|
||||
orderId = approveResponse.orderId,
|
||||
paymentKey = approveResponse.paymentKey,
|
||||
totalAmount = approveResponse.totalAmount,
|
||||
reservation = reservation,
|
||||
approvedAt = approveResponse.approvedAt
|
||||
)
|
||||
|
||||
return paymentRepository.save(payment).toCreateResponse()
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun isReservationPaid(
|
||||
reservationId: Long
|
||||
): Boolean = paymentRepository.existsByReservationId(reservationId)
|
||||
fun isReservationPaid(reservationId: Long): Boolean = paymentRepository.existsByReservationId(reservationId)
|
||||
|
||||
@Transactional
|
||||
fun createCanceledPayment(
|
||||
cancelInfo: PaymentCancelResponse,
|
||||
approvedAt: OffsetDateTime,
|
||||
paymentKey: String
|
||||
): CanceledPaymentEntity = CanceledPaymentEntity(
|
||||
paymentKey = paymentKey,
|
||||
cancelReason = cancelInfo.cancelReason,
|
||||
cancelAmount = cancelInfo.cancelAmount,
|
||||
approvedAt = approvedAt,
|
||||
canceledAt = cancelInfo.canceledAt
|
||||
).also { canceledPaymentRepository.save(it) }
|
||||
): CanceledPaymentEntity {
|
||||
val canceledPayment = CanceledPaymentEntity(
|
||||
paymentKey = paymentKey,
|
||||
cancelReason = cancelInfo.cancelReason,
|
||||
cancelAmount = cancelInfo.cancelAmount,
|
||||
approvedAt = approvedAt,
|
||||
canceledAt = cancelInfo.canceledAt
|
||||
)
|
||||
|
||||
return canceledPaymentRepository.save(canceledPayment)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun createCanceledPaymentByReservationId(reservationId: Long): PaymentCancelRequest {
|
||||
val paymentKey: String = paymentRepository.findPaymentKeyByReservationId(reservationId)
|
||||
?: throw RoomescapeException(
|
||||
ErrorType.PAYMENT_NOT_FOUND,
|
||||
"[reservationId: $reservationId]",
|
||||
HttpStatus.NOT_FOUND
|
||||
)
|
||||
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||
|
||||
// 취소 시간은 현재 시간으로 일단 생성한 뒤, 결제 취소 완료 후 해당 시간으로 변경합니다.
|
||||
val canceled: CanceledPaymentEntity = cancelPayment(paymentKey)
|
||||
|
||||
@ -73,23 +73,19 @@ class PaymentService(
|
||||
cancelReason: String = "고객 요청",
|
||||
canceledAt: OffsetDateTime = OffsetDateTime.now()
|
||||
): CanceledPaymentEntity {
|
||||
val paymentEntity: PaymentEntity = paymentRepository.findByPaymentKey(paymentKey)
|
||||
val payment: PaymentEntity = paymentRepository.findByPaymentKey(paymentKey)
|
||||
?.also { paymentRepository.delete(it) }
|
||||
?: throw RoomescapeException(
|
||||
ErrorType.PAYMENT_NOT_FOUND,
|
||||
"[paymentKey: $paymentKey]",
|
||||
HttpStatus.NOT_FOUND
|
||||
)
|
||||
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||
|
||||
return CanceledPaymentEntity(
|
||||
val canceledPayment = CanceledPaymentEntity(
|
||||
paymentKey = paymentKey,
|
||||
cancelReason = cancelReason,
|
||||
cancelAmount = paymentEntity.totalAmount,
|
||||
approvedAt = paymentEntity.approvedAt,
|
||||
cancelAmount = payment.totalAmount,
|
||||
approvedAt = payment.approvedAt,
|
||||
canceledAt = canceledAt
|
||||
).also {
|
||||
canceledPaymentRepository.save(it)
|
||||
}
|
||||
)
|
||||
|
||||
return canceledPaymentRepository.save(canceledPayment)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@ -97,12 +93,8 @@ class PaymentService(
|
||||
paymentKey: String,
|
||||
canceledAt: OffsetDateTime
|
||||
) {
|
||||
canceledPaymentRepository.findByPaymentKey(paymentKey)?.let {
|
||||
it.canceledAt = canceledAt
|
||||
} ?: throw RoomescapeException(
|
||||
ErrorType.PAYMENT_NOT_FOUND,
|
||||
"[paymentKey: $paymentKey]",
|
||||
HttpStatus.NOT_FOUND
|
||||
)
|
||||
canceledPaymentRepository.findByPaymentKey(paymentKey)
|
||||
?.apply { this.canceledAt = canceledAt }
|
||||
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package roomescape.payment.exception
|
||||
|
||||
import org.springframework.http.HttpStatus
|
||||
import roomescape.common.exception.ErrorCode
|
||||
|
||||
enum class PaymentErrorCode(
|
||||
override val httpStatus: HttpStatus,
|
||||
override val errorCode: String,
|
||||
override val message: String
|
||||
) : ErrorCode {
|
||||
PAYMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "P001", "결제 정보를 찾을 수 없어요."),
|
||||
CANCELED_PAYMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "P002", "취소된 결제 정보를 찾을 수 없어요."),
|
||||
PAYMENT_CLIENT_ERROR(HttpStatus.BAD_REQUEST, "P003", "결제에 실패했어요. 결제 수단을 확인한 후 다시 시도해주세요."),
|
||||
|
||||
PAYMENT_PROVIDER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "P999", "시스템에 일시적인 오류가 발생했어요. 잠시 후 다시 시도해주세요.")
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
package roomescape.payment.exception
|
||||
|
||||
import roomescape.common.exception.RoomescapeExceptionV2
|
||||
|
||||
class PaymentException(
|
||||
override val errorCode: PaymentErrorCode,
|
||||
override val message: String = errorCode.message
|
||||
) : RoomescapeExceptionV2(errorCode, message)
|
||||
@ -11,6 +11,8 @@ import io.mockk.runs
|
||||
import org.springframework.http.HttpStatus
|
||||
import roomescape.common.exception.ErrorType
|
||||
import roomescape.common.exception.RoomescapeException
|
||||
import roomescape.payment.exception.PaymentErrorCode
|
||||
import roomescape.payment.exception.PaymentException
|
||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
||||
import roomescape.payment.infrastructure.persistence.PaymentRepository
|
||||
import roomescape.payment.web.PaymentCancelRequest
|
||||
@ -23,19 +25,15 @@ class PaymentServiceTest : FunSpec({
|
||||
|
||||
val paymentService = PaymentService(paymentRepository, canceledPaymentRepository)
|
||||
|
||||
context("cancelPaymentByAdmin") {
|
||||
context("createCanceledPaymentByReservationId") {
|
||||
val reservationId = 1L
|
||||
test("reservationId로 paymentKey를 찾을 수 없으면 예외를 던진다.") {
|
||||
every { paymentRepository.findPaymentKeyByReservationId(reservationId) } returns null
|
||||
|
||||
val exception = shouldThrow<RoomescapeException> {
|
||||
val exception = shouldThrow<PaymentException> {
|
||||
paymentService.createCanceledPaymentByReservationId(reservationId)
|
||||
}
|
||||
|
||||
assertSoftly(exception) {
|
||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
||||
}
|
||||
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||
}
|
||||
|
||||
context("reservationId로 paymentKey를 찾고난 후") {
|
||||
@ -50,14 +48,10 @@ class PaymentServiceTest : FunSpec({
|
||||
paymentRepository.findByPaymentKey(paymentKey)
|
||||
} returns null
|
||||
|
||||
val exception = shouldThrow<RoomescapeException> {
|
||||
val exception = shouldThrow<PaymentException> {
|
||||
paymentService.createCanceledPaymentByReservationId(reservationId)
|
||||
}
|
||||
|
||||
assertSoftly(exception) {
|
||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
||||
}
|
||||
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||
}
|
||||
|
||||
test("해당 paymentKey로 paymentEntity를 찾고, cancelPaymentEntity를 저장한다.") {
|
||||
@ -76,6 +70,7 @@ class PaymentServiceTest : FunSpec({
|
||||
} returns PaymentFixture.createCanceled(
|
||||
id = 1L,
|
||||
paymentKey = paymentKey,
|
||||
cancelReason = "Test",
|
||||
cancelAmount = paymentEntity.totalAmount,
|
||||
)
|
||||
|
||||
@ -84,7 +79,7 @@ class PaymentServiceTest : FunSpec({
|
||||
assertSoftly(result) {
|
||||
this.paymentKey shouldBe paymentKey
|
||||
this.amount shouldBe paymentEntity.totalAmount
|
||||
this.cancelReason shouldBe "고객 요청"
|
||||
this.cancelReason shouldBe "Test"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,14 +94,10 @@ class PaymentServiceTest : FunSpec({
|
||||
canceledPaymentRepository.findByPaymentKey(paymentKey)
|
||||
} returns null
|
||||
|
||||
val exception = shouldThrow<RoomescapeException> {
|
||||
val exception = shouldThrow<PaymentException> {
|
||||
paymentService.updateCanceledTime(paymentKey, canceledAt)
|
||||
}
|
||||
|
||||
assertSoftly(exception) {
|
||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
||||
}
|
||||
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||
}
|
||||
|
||||
test("paymentKey로 canceledPaymentEntity를 찾고, canceledAt을 업데이트한다.") {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user