From 0d33579d3fedf6f8460974d0226a5c9575a4e40a Mon Sep 17 00:00:00 2001 From: pricelees Date: Wed, 23 Jul 2025 17:38:24 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20time=20=EB=8F=84=EB=A9=94=EC=9D=B8?= =?UTF-8?q?=EC=9D=98=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../persistence/ReservationRepository.kt | 2 +- .../roomescape/time/business/TimeService.kt | 47 +++++++------------ .../time/exception/TimeErrorCode.kt | 14 ++++++ .../time/exception/TimeException.kt | 9 ++++ .../kotlin/roomescape/time/web/TimeDTO.kt | 8 ++-- 5 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 src/main/kotlin/roomescape/time/exception/TimeErrorCode.kt create mode 100644 src/main/kotlin/roomescape/time/exception/TimeException.kt diff --git a/src/main/kotlin/roomescape/reservation/infrastructure/persistence/ReservationRepository.kt b/src/main/kotlin/roomescape/reservation/infrastructure/persistence/ReservationRepository.kt index a0a4f499..3dd73807 100644 --- a/src/main/kotlin/roomescape/reservation/infrastructure/persistence/ReservationRepository.kt +++ b/src/main/kotlin/roomescape/reservation/infrastructure/persistence/ReservationRepository.kt @@ -11,7 +11,7 @@ import java.time.LocalDate interface ReservationRepository : JpaRepository, JpaSpecificationExecutor { - fun findByTime(time: TimeEntity): List + fun findAllByTime(time: TimeEntity): List fun findByDateAndThemeId(date: LocalDate, themeId: Long): List diff --git a/src/main/kotlin/roomescape/time/business/TimeService.kt b/src/main/kotlin/roomescape/time/business/TimeService.kt index 7b8d956a..799a363f 100644 --- a/src/main/kotlin/roomescape/time/business/TimeService.kt +++ b/src/main/kotlin/roomescape/time/business/TimeService.kt @@ -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 = reservationRepository.findAllByTime(time) + + if (reservations.isNotEmpty()) { + throw TimeException(TimeErrorCode.TIME_ALREADY_RESERVED) + } + timeRepository.delete(time) } @Transactional(readOnly = true) @@ -66,8 +56,7 @@ class TimeService( return TimeWithAvailabilityListResponse(allTimes.map { time -> val isAvailable: Boolean = reservations.none { reservation -> reservation.time.id == time.id } - TimeWithAvailabilityResponse(time.id!!, time.startAt, isAvailable) }) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/roomescape/time/exception/TimeErrorCode.kt b/src/main/kotlin/roomescape/time/exception/TimeErrorCode.kt new file mode 100644 index 00000000..c0c967f3 --- /dev/null +++ b/src/main/kotlin/roomescape/time/exception/TimeErrorCode.kt @@ -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", "예약된 시간이라 삭제할 수 없어요.") +} diff --git a/src/main/kotlin/roomescape/time/exception/TimeException.kt b/src/main/kotlin/roomescape/time/exception/TimeException.kt new file mode 100644 index 00000000..a073fdc6 --- /dev/null +++ b/src/main/kotlin/roomescape/time/exception/TimeException.kt @@ -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) diff --git a/src/main/kotlin/roomescape/time/web/TimeDTO.kt b/src/main/kotlin/roomescape/time/web/TimeDTO.kt index 257d7ff8..7c36ebed 100644 --- a/src/main/kotlin/roomescape/time/web/TimeDTO.kt +++ b/src/main/kotlin/roomescape/time/web/TimeDTO.kt @@ -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 ) -fun List.toRetrieveListResponse(): TimeRetrieveListResponse = TimeRetrieveListResponse( - this.map { it.toRetrieveResponse() } +fun List.toResponse(): TimeRetrieveListResponse = TimeRetrieveListResponse( + this.map { it.toResponse() } ) data class TimeWithAvailabilityResponse(