[#20] 도메인별 예외 분리 #21

Merged
pricelees merged 37 commits from refactor/#20 into main 2025-07-24 02:48:53 +00:00
5 changed files with 47 additions and 33 deletions
Showing only changes of commit 0d33579d3f - Show all commits

View File

@ -11,7 +11,7 @@ import java.time.LocalDate
interface ReservationRepository
: JpaRepository<ReservationEntity, Long>, JpaSpecificationExecutor<ReservationEntity> {
fun findByTime(time: TimeEntity): List<ReservationEntity>
fun findAllByTime(time: TimeEntity): List<ReservationEntity>
fun findByDateAndThemeId(date: LocalDate, themeId: Long): List<ReservationEntity>

View File

@ -1,13 +1,12 @@
package roomescape.time.business
import org.springframework.data.repository.findByIdOrNull
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.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationRepository
import roomescape.time.exception.TimeErrorCode
import roomescape.time.exception.TimeException
import roomescape.time.infrastructure.persistence.TimeEntity
import roomescape.time.infrastructure.persistence.TimeRepository
import roomescape.time.web.*
@ -21,42 +20,33 @@ class TimeService(
) {
@Transactional(readOnly = true)
fun findById(id: Long): TimeEntity = timeRepository.findByIdOrNull(id)
?: throw RoomescapeException(
ErrorType.TIME_NOT_FOUND,
"[timeId: $id]",
HttpStatus.BAD_REQUEST
)
?: throw TimeException(TimeErrorCode.TIME_NOT_FOUND)
@Transactional(readOnly = true)
fun findTimes(): TimeRetrieveListResponse = timeRepository.findAll().toRetrieveListResponse()
fun findTimes(): TimeRetrieveListResponse = timeRepository.findAll()
.toResponse()
@Transactional
fun createTime(timeCreateRequest: TimeCreateRequest): TimeCreateResponse {
val startAt: LocalTime = timeCreateRequest.startAt
fun createTime(request: TimeCreateRequest): TimeCreateResponse {
val startAt: LocalTime = request.startAt
if (timeRepository.existsByStartAt(startAt)) {
throw RoomescapeException(
ErrorType.TIME_DUPLICATED, "[startAt: $startAt]", HttpStatus.CONFLICT
)
throw TimeException(TimeErrorCode.TIME_DUPLICATED)
}
return TimeEntity(startAt = startAt)
.also { timeRepository.save(it) }
.toCreateResponse()
val time: TimeEntity = request.toEntity()
return timeRepository.save(time).toCreateResponse()
}
@Transactional
fun deleteTime(id: Long) {
val time: TimeEntity = findById(id)
reservationRepository.findByTime(time)
.also {
if (it.isNotEmpty()) {
throw RoomescapeException(
ErrorType.TIME_IS_USED_CONFLICT, "[timeId: $id]", HttpStatus.CONFLICT
)
}
timeRepository.deleteById(id)
val reservations: List<ReservationEntity> = reservationRepository.findAllByTime(time)
if (reservations.isNotEmpty()) {
throw TimeException(TimeErrorCode.TIME_ALREADY_RESERVED)
}
timeRepository.delete(time)
}
@Transactional(readOnly = true)
@ -66,7 +56,6 @@ class TimeService(
return TimeWithAvailabilityListResponse(allTimes.map { time ->
val isAvailable: Boolean = reservations.none { reservation -> reservation.time.id == time.id }
TimeWithAvailabilityResponse(time.id!!, time.startAt, isAvailable)
})
}

View File

@ -0,0 +1,14 @@
package roomescape.time.exception
import org.springframework.http.HttpStatus
import roomescape.common.exception.ErrorCode
enum class TimeErrorCode(
override val httpStatus: HttpStatus,
override val errorCode: String,
override val message: String
) : ErrorCode {
TIME_NOT_FOUND(HttpStatus.NOT_FOUND, "TM001", "시간을 찾을 수 없어요."),
TIME_DUPLICATED(HttpStatus.BAD_REQUEST, "TM002", "이미 같은 시간이 있어요."),
TIME_ALREADY_RESERVED(HttpStatus.CONFLICT, "TM003", "예약된 시간이라 삭제할 수 없어요.")
}

View File

@ -0,0 +1,9 @@
package roomescape.time.exception
import roomescape.common.exception.ErrorCode
import roomescape.common.exception.RoomescapeExceptionV2
class TimeException(
override val errorCode: ErrorCode,
override val message: String = errorCode.message
) : RoomescapeExceptionV2(errorCode, message)

View File

@ -10,6 +10,8 @@ data class TimeCreateRequest(
val startAt: LocalTime
)
fun TimeCreateRequest.toEntity(): TimeEntity = TimeEntity(startAt = this.startAt)
@Schema(name = "예약 시간 정보", description = "예약 시간 추가 및 조회 응답시 사용됩니다.")
data class TimeCreateResponse(
@Schema(description = "시간 식별자")
@ -29,14 +31,14 @@ data class TimeRetrieveResponse(
val startAt: LocalTime
)
fun TimeEntity.toRetrieveResponse(): TimeRetrieveResponse = TimeRetrieveResponse(this.id!!, this.startAt)
fun TimeEntity.toResponse(): TimeRetrieveResponse = TimeRetrieveResponse(this.id!!, this.startAt)
data class TimeRetrieveListResponse(
val times: List<TimeRetrieveResponse>
)
fun List<TimeEntity>.toRetrieveListResponse(): TimeRetrieveListResponse = TimeRetrieveListResponse(
this.map { it.toRetrieveResponse() }
fun List<TimeEntity>.toResponse(): TimeRetrieveListResponse = TimeRetrieveListResponse(
this.map { it.toResponse() }
)
data class TimeWithAvailabilityResponse(