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 new file mode 100644 index 00000000..7bebf555 --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderErrorCode.kt @@ -0,0 +1,20 @@ +package com.sangdol.roomescape.order.exception + +import com.sangdol.common.types.exception.ErrorCode +import com.sangdol.common.types.web.HttpStatus + +enum class OrderErrorCode( + override val httpStatus: HttpStatus, + override val errorCode: String, + override val message: String +) : ErrorCode { + NOT_CONFIRMABLE(HttpStatus.CONFLICT, "B000", "예약을 확정할 수 없어요."), + BOOKING_PAYMENT_TIMEOUT(HttpStatus.CONFLICT, "B001", "결제 가능 시간을 초과했어요. 처음부터 다시 시도해주세요."), + BOOKING_ALREADY_COMPLETED(HttpStatus.CONFLICT, "B002", "이미 완료된 예약이에요."), + EXPIRED_RESERVATION(HttpStatus.CONFLICT, "B003", "결제 가능 시간이 지나 만료된 예약이에요. 처음부터 다시 시도해주세요."), + CANCELED_RESERVATION(HttpStatus.CONFLICT, "B004", "이미 취소된 예약이에요. 본인이 취소하지 않았다면 매장에 문의해주세요."), + PAST_SCHEDULE(HttpStatus.CONFLICT, "B005", "지난 일정은 예약할 수 없어요."), + + BOOKING_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 new file mode 100644 index 00000000..2306f9d4 --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderException.kt @@ -0,0 +1,16 @@ +package com.sangdol.roomescape.order.exception + +import com.sangdol.common.types.exception.ErrorCode +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 +) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderExceptionHandler.kt b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderExceptionHandler.kt new file mode 100644 index 00000000..0b72d953 --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/order/exception/OrderExceptionHandler.kt @@ -0,0 +1,45 @@ +package com.sangdol.roomescape.order.exception + +import com.sangdol.common.types.exception.ErrorCode +import com.sangdol.common.types.web.HttpStatus +import com.sangdol.common.web.support.log.WebLogMessageConverter +import io.github.oshai.kotlinlogging.KLogger +import io.github.oshai.kotlinlogging.KotlinLogging +import jakarta.servlet.http.HttpServletRequest +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.bind.annotation.RestControllerAdvice + +private val log: KLogger = KotlinLogging.logger {} + +@RestControllerAdvice +class OrderExceptionHandler( + private val messageConverter: WebLogMessageConverter +) { + @ExceptionHandler(OrderException::class) + fun handleOrderException( + servletRequest: HttpServletRequest, + e: OrderException + ): ResponseEntity { + val errorCode: ErrorCode = e.errorCode + val httpStatus: HttpStatus = errorCode.httpStatus + val errorResponse = OrderErrorResponse( + code = errorCode.errorCode, + message = e.message, + trial = e.trial + ) + + log.info { + messageConverter.convertToErrorResponseMessage( + servletRequest = servletRequest, + httpStatus = httpStatus, + responseBody = errorResponse, + exception = if (errorCode.message == e.message) null else e + ) + } + + return ResponseEntity + .status(httpStatus.value()) + .body(errorResponse) + } +}