diff --git a/src/main/kotlin/roomescape/reservation/business/ReservationService.kt b/src/main/kotlin/roomescape/reservation/business/ReservationService.kt index fc67d4cd..f59889e9 100644 --- a/src/main/kotlin/roomescape/reservation/business/ReservationService.kt +++ b/src/main/kotlin/roomescape/reservation/business/ReservationService.kt @@ -7,9 +7,10 @@ import org.springframework.data.repository.findByIdOrNull import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import roomescape.common.config.next -import roomescape.member.business.MemberService -import roomescape.member.infrastructure.persistence.Role -import roomescape.member.web.MemberSummaryRetrieveResponse +import roomescape.common.dto.CurrentUserContext +import roomescape.common.dto.PrincipalType +import roomescape.member.business.UserService +import roomescape.member.web.UserContactRetrieveResponse import roomescape.payment.business.PaymentService import roomescape.payment.web.PaymentRetrieveResponse import roomescape.reservation.exception.ReservationErrorCode @@ -31,7 +32,7 @@ class ReservationService( private val reservationRepository: ReservationRepository, private val reservationValidator: ReservationValidator, private val scheduleService: ScheduleService, - private val memberService: MemberService, + private val userService: UserService, private val themeService: ThemeService, private val canceledReservationRepository: CanceledReservationRepository, private val tsidFactory: TsidFactory, @@ -40,14 +41,14 @@ class ReservationService( @Transactional fun createPendingReservation( - memberId: Long, + user: CurrentUserContext, request: PendingReservationCreateRequest ): PendingReservationCreateResponse { log.info { "[ReservationService.createPendingReservation] Pending 예약 생성 시작: schedule=${request.scheduleId}" } validateCanCreate(request) - val reservation: ReservationEntity = request.toEntity(id = tsidFactory.next(), memberId = memberId) + val reservation: ReservationEntity = request.toEntity(id = tsidFactory.next(), userId = user.id) return PendingReservationCreateResponse(reservationRepository.save(reservation).id) .also { "[ReservationService.createPendingReservation] Pending 예약 생성 완료: reservationId=${it}, schedule=${request.scheduleId}" } @@ -70,18 +71,17 @@ class ReservationService( } @Transactional - fun cancelReservation(memberId: Long, reservationId: Long, request: ReservationCancelRequest) { - log.info { "[ReservationService.cancelReservation] 예약 취소 시작: memberId=${memberId}, reservationId=${reservationId}" } + fun cancelReservation(user: CurrentUserContext, reservationId: Long, request: ReservationCancelRequest) { + log.info { "[ReservationService.cancelReservation] 예약 취소 시작: userId=${user.id}, reservationId=${reservationId}" } val reservation: ReservationEntity = findOrThrow(reservationId) - val member: MemberSummaryRetrieveResponse = memberService.findSummaryById(memberId) run { scheduleService.updateSchedule( reservation.scheduleId, ScheduleUpdateRequest(status = ScheduleStatus.AVAILABLE) ) - saveCanceledReservation(member, reservation, request.cancelReason) + saveCanceledReservation(user, reservation, request.cancelReason) reservation.cancel() }.also { log.info { "[ReservationService.cancelReservation] 예약 취소 완료: reservationId=${reservationId}" } @@ -89,10 +89,10 @@ class ReservationService( } @Transactional(readOnly = true) - fun findSummaryByMemberId(memberId: Long): ReservationSummaryRetrieveListResponse { - log.info { "[ReservationService.findSummaryByMemberId] 예약 조회 시작: memberId=${memberId}" } + fun findUserSummaryReservation(user: CurrentUserContext): ReservationSummaryRetrieveListResponse { + log.info { "[ReservationService.findSummaryByMemberId] 예약 조회 시작: userId=${user.id}" } - val reservations: List = reservationRepository.findAllByMemberId(memberId) + val reservations: List = reservationRepository.findAllByUserId(user.id) return ReservationSummaryRetrieveListResponse(reservations.map { val schedule: ScheduleSummaryResponse = scheduleService.findSummaryById(it.scheduleId) @@ -106,7 +106,7 @@ class ReservationService( status = it.status ) }).also { - log.info { "[ReservationService.findSummaryByMemberId] ${it.reservations.size}개의 예약 조회 완료: memberId=${memberId}" } + log.info { "[ReservationService.findSummaryByMemberId] ${it.reservations.size}개의 예약 조회 완료: userId=${user.id}" } } } @@ -115,11 +115,11 @@ class ReservationService( log.info { "[ReservationService.findDetailById] 예약 상세 조회 시작: reservationId=${id}" } val reservation: ReservationEntity = findOrThrow(id) - val member: MemberSummaryRetrieveResponse = memberService.findSummaryById(reservation.memberId) + val user: UserContactRetrieveResponse = userService.findContactById(reservation.userId) val paymentDetail: PaymentRetrieveResponse = paymentService.findDetailByReservationId(id) return reservation.toReservationDetailRetrieveResponse( - member = member, + user = user, payment = paymentDetail ).also { log.info { "[ReservationService.findDetailById] 예약 상세 조회 완료: reservationId=${id}" } @@ -138,19 +138,19 @@ class ReservationService( } private fun saveCanceledReservation( - member: MemberSummaryRetrieveResponse, + user: CurrentUserContext, reservation: ReservationEntity, cancelReason: String ) { - if (member.role != Role.ADMIN && reservation.memberId != member.id) { - log.warn { "[ReservationService.createCanceledPayment] 예약자 본인 또는 관리자가 아닌 회원의 취소 요청: reservationId=${reservation.id}, memberId=${member.id}" } + if (user.type != PrincipalType.ADMIN && reservation.userId != user.id) { + log.warn { "[ReservationService.createCanceledPayment] 예약자 본인 또는 관리자가 아닌 회원의 취소 요청: reservationId=${reservation.id}, userId=${user.id}" } throw ReservationException(ReservationErrorCode.NO_PERMISSION_TO_CANCEL_RESERVATION) } CanceledReservationEntity( id = tsidFactory.next(), reservationId = reservation.id, - canceledBy = member.id, + canceledBy = user.id, cancelReason = cancelReason, canceledAt = LocalDateTime.now(), status = CanceledReservationStatus.PROCESSING diff --git a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt index 2d25ff0a..262f7329 100644 --- a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt +++ b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt @@ -1,16 +1,14 @@ package roomescape.reservation.docs import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestBody +import roomescape.auth.web.support.Authenticated import roomescape.auth.web.support.CurrentUser -import roomescape.auth.web.support.LoginRequired -import roomescape.auth.web.support.MemberId import roomescape.auth.web.support.UserOnly import roomescape.common.dto.CurrentUserContext import roomescape.common.dto.response.CommonApiResponse @@ -18,6 +16,7 @@ import roomescape.reservation.web.* interface ReservationAPI { + @UserOnly @Operation(summary = "결제 대기 예약 저장", tags = ["로그인이 필요한 API"]) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) fun createPendingReservation( @@ -32,7 +31,7 @@ interface ReservationAPI { @PathVariable("id") id: Long ): ResponseEntity> - @UserOnly + @Authenticated @Operation(summary = "예약 취소", tags = ["로그인이 필요한 API"]) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) fun cancelReservation( @@ -41,6 +40,7 @@ interface ReservationAPI { @Valid @RequestBody request: ReservationCancelRequest ): ResponseEntity> + @UserOnly @Operation(summary = "회원별 예약 요약 목록 조회", tags = ["로그인이 필요한 API"]) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) fun findSummaryByMemberId( diff --git a/src/main/kotlin/roomescape/reservation/web/ReservationController.kt b/src/main/kotlin/roomescape/reservation/web/ReservationController.kt index dedf02f5..ae0652cb 100644 --- a/src/main/kotlin/roomescape/reservation/web/ReservationController.kt +++ b/src/main/kotlin/roomescape/reservation/web/ReservationController.kt @@ -19,7 +19,7 @@ class ReservationController( @CurrentUser user: CurrentUserContext, @Valid @RequestBody request: PendingReservationCreateRequest ): ResponseEntity> { - val response = reservationService.createPendingReservation(user.id, request) + val response = reservationService.createPendingReservation(user, request) return ResponseEntity.ok(CommonApiResponse(response)) } @@ -39,7 +39,7 @@ class ReservationController( @PathVariable reservationId: Long, @Valid @RequestBody request: ReservationCancelRequest ): ResponseEntity> { - reservationService.cancelReservation(user.id, reservationId, request) + reservationService.cancelReservation(user, reservationId, request) return ResponseEntity.ok().body(CommonApiResponse()) } @@ -48,7 +48,7 @@ class ReservationController( override fun findSummaryByMemberId( @CurrentUser user: CurrentUserContext, ): ResponseEntity> { - val response = reservationService.findSummaryByMemberId(user.id) + val response = reservationService.findUserSummaryReservation(user) return ResponseEntity.ok(CommonApiResponse(response)) } diff --git a/src/main/kotlin/roomescape/reservation/web/ReservationDto.kt b/src/main/kotlin/roomescape/reservation/web/ReservationDto.kt index 5e5050cb..beeadf1f 100644 --- a/src/main/kotlin/roomescape/reservation/web/ReservationDto.kt +++ b/src/main/kotlin/roomescape/reservation/web/ReservationDto.kt @@ -1,7 +1,7 @@ package roomescape.reservation.web import jakarta.validation.constraints.NotEmpty -import roomescape.member.web.MemberSummaryRetrieveResponse +import roomescape.member.web.UserContactRetrieveResponse import roomescape.payment.web.PaymentRetrieveResponse import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationStatus @@ -48,18 +48,18 @@ data class ReservationSummaryRetrieveListResponse( data class ReservationDetailRetrieveResponse( val id: Long, - val member: MemberSummaryRetrieveResponse, + val user: UserContactRetrieveResponse, val applicationDateTime: LocalDateTime, val payment: PaymentRetrieveResponse, ) fun ReservationEntity.toReservationDetailRetrieveResponse( - member: MemberSummaryRetrieveResponse, + user: UserContactRetrieveResponse, payment: PaymentRetrieveResponse, ): ReservationDetailRetrieveResponse { return ReservationDetailRetrieveResponse( id = this.id, - member = member, + user = user, applicationDateTime = this.createdAt, payment = payment, )