generated from pricelees/issue-pr-template
refactor: 예약 API 명세 및 컨트롤러 재정의
This commit is contained in:
parent
ddf366c587
commit
5a9d992cb4
@ -2,150 +2,59 @@ package roomescape.reservation.docs
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import io.swagger.v3.oas.annotations.Parameter
|
||||
import io.swagger.v3.oas.annotations.headers.Header
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses
|
||||
import io.swagger.v3.oas.annotations.tags.Tag
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import roomescape.auth.web.support.Admin
|
||||
import roomescape.auth.web.support.LoginRequired
|
||||
import roomescape.auth.web.support.MemberId
|
||||
import roomescape.common.dto.response.CommonApiResponse
|
||||
import roomescape.reservation.web.*
|
||||
import java.time.LocalDate
|
||||
import roomescape.reservation.web.PendingReservationCreateRequest
|
||||
import roomescape.reservation.web.PendingReservationCreateResponse
|
||||
import roomescape.reservation.web.ReservationCancelRequest
|
||||
import roomescape.reservation.web.ReservationDetailRetrieveResponse
|
||||
import roomescape.reservation.web.ReservationSummaryRetrieveListResponse
|
||||
|
||||
@Tag(name = "3. 예약 API", description = "예약 및 대기 정보를 추가 / 조회 / 삭제할 때 사용합니다.")
|
||||
interface ReservationAPI {
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "모든 예약 정보 조회", tags = ["관리자 로그인이 필요한 API"])
|
||||
@LoginRequired
|
||||
@Operation(summary = "결제 대기 예약 저장", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||
fun findReservations(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
|
||||
fun createPendingReservation(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@Valid @RequestBody request: PendingReservationCreateRequest
|
||||
): ResponseEntity<CommonApiResponse<PendingReservationCreateResponse>>
|
||||
|
||||
@LoginRequired
|
||||
@Operation(summary = "자신의 예약 및 대기 조회", tags = ["로그인이 필요한 API"])
|
||||
@Operation(summary = "예약 확정", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||
fun findReservationsByMemberId(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<MyReservationRetrieveListResponse>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "관리자의 예약 검색", description = "특정 조건에 해당되는 예약 검색", tags = ["관리자 로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)
|
||||
)
|
||||
fun searchReservations(
|
||||
@RequestParam(required = false) themeId: Long?,
|
||||
@RequestParam(required = false) memberId: Long?,
|
||||
@RequestParam(required = false) dateFrom: LocalDate?,
|
||||
@RequestParam(required = false) dateTo: LocalDate?
|
||||
): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "관리자의 예약 취소", tags = ["관리자 로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(responseCode = "204", description = "성공"),
|
||||
)
|
||||
fun cancelReservationByAdmin(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") reservationId: Long
|
||||
fun confirmReservation(
|
||||
@PathVariable("id") id: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>>
|
||||
|
||||
@LoginRequired
|
||||
@Operation(summary = "예약 추가", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(
|
||||
responseCode = "201",
|
||||
description = "성공",
|
||||
useReturnTypeSchema = true,
|
||||
headers = [Header(
|
||||
name = HttpHeaders.LOCATION,
|
||||
description = "생성된 예약 정보 URL",
|
||||
schema = Schema(example = "/reservations/1")
|
||||
)]
|
||||
)
|
||||
)
|
||||
fun createReservationWithPayment(
|
||||
@Valid @RequestBody reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "관리자 예약 추가", tags = ["관리자 로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(
|
||||
responseCode = "201",
|
||||
description = "성공",
|
||||
useReturnTypeSchema = true,
|
||||
headers = [Header(
|
||||
name = HttpHeaders.LOCATION,
|
||||
description = "생성된 예약 정보 URL",
|
||||
schema = Schema(example = "/reservations/1")
|
||||
)],
|
||||
)
|
||||
)
|
||||
fun createReservationByAdmin(
|
||||
@Valid @RequestBody adminReservationRequest: AdminReservationCreateRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "모든 예약 대기 조회", tags = ["관리자 로그인이 필요한 API"])
|
||||
@Operation(summary = "예약 취소", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||
fun findAllWaiting(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
|
||||
fun cancelReservation(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable reservationId: Long,
|
||||
@Valid @RequestBody request: ReservationCancelRequest
|
||||
): ResponseEntity<CommonApiResponse<Unit>>
|
||||
|
||||
@LoginRequired
|
||||
@Operation(summary = "예약 대기 신청", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(
|
||||
responseCode = "201",
|
||||
description = "성공",
|
||||
useReturnTypeSchema = true,
|
||||
headers = [Header(
|
||||
name = HttpHeaders.LOCATION,
|
||||
description = "생성된 예약 정보 URL",
|
||||
schema = Schema(example = "/reservations/1")
|
||||
)]
|
||||
)
|
||||
)
|
||||
fun createWaiting(
|
||||
@Valid @RequestBody waitingCreateRequest: WaitingCreateRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>>
|
||||
@Operation(summary = "회원별 예약 요약 목록 조회", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||
fun findSummaryByMemberId(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationSummaryRetrieveListResponse>>
|
||||
|
||||
@LoginRequired
|
||||
@Operation(summary = "예약 대기 취소", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(responseCode = "204", description = "성공"),
|
||||
)
|
||||
fun cancelWaitingByMember(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") @Parameter(description = "예약 ID") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>>
|
||||
@Operation(summary = "특정 예약에 대한 상세 조회", tags = ["로그인이 필요한 API"])
|
||||
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
|
||||
fun findDetailById(
|
||||
@PathVariable("id") id: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationDetailRetrieveResponse>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "대기 중인 예약 승인", tags = ["관리자 로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(responseCode = "200", description = "성공"),
|
||||
)
|
||||
fun confirmWaiting(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") @Parameter(description = "예약 ID") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>>
|
||||
|
||||
@Admin
|
||||
@Operation(summary = "대기 중인 예약 거절", tags = ["관리자 로그인이 필요한 API"])
|
||||
@ApiResponses(
|
||||
ApiResponse(responseCode = "204", description = "대기 중인 예약 거절 성공"),
|
||||
)
|
||||
fun rejectWaiting(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") @Parameter(description = "예약 ID") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>>
|
||||
}
|
||||
}
|
||||
@ -6,170 +6,59 @@ import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import roomescape.auth.web.support.MemberId
|
||||
import roomescape.common.dto.response.CommonApiResponse
|
||||
import roomescape.payment.infrastructure.client.PaymentApproveRequest
|
||||
import roomescape.payment.infrastructure.client.PaymentApproveResponse
|
||||
import roomescape.payment.infrastructure.client.TossPaymentClient
|
||||
import roomescape.payment.web.PaymentCancelRequest
|
||||
import roomescape.reservation.business.ReservationWriteService
|
||||
import roomescape.reservation.business.ReservationFindService
|
||||
import roomescape.reservation.business.ReservationWithPaymentService
|
||||
import roomescape.reservation.business.ReservationService
|
||||
import roomescape.reservation.docs.ReservationAPI
|
||||
import java.net.URI
|
||||
import java.time.LocalDate
|
||||
|
||||
@RestController
|
||||
class ReservationController(
|
||||
private val reservationWithPaymentService: ReservationWithPaymentService,
|
||||
private val reservationFindService: ReservationFindService,
|
||||
private val reservationWriteService: ReservationWriteService,
|
||||
private val paymentClient: TossPaymentClient
|
||||
private val reservationService: ReservationService
|
||||
) : ReservationAPI {
|
||||
@GetMapping("/reservations")
|
||||
override fun findReservations(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
|
||||
val response: ReservationRetrieveListResponse = reservationFindService.findReservations()
|
||||
|
||||
@PostMapping("/reservations/pending")
|
||||
override fun createPendingReservation(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@Valid @RequestBody request: PendingReservationCreateRequest
|
||||
): ResponseEntity<CommonApiResponse<PendingReservationCreateResponse>> {
|
||||
val response = reservationService.createPendingReservation(memberId, request)
|
||||
|
||||
return ResponseEntity.ok(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@GetMapping("/reservations-mine")
|
||||
override fun findReservationsByMemberId(
|
||||
@PatchMapping("/reservations/{id}/confirm")
|
||||
override fun confirmReservation(
|
||||
@PathVariable("id") id: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
reservationService.confirmReservation(id)
|
||||
|
||||
return ResponseEntity.ok().body(CommonApiResponse())
|
||||
}
|
||||
|
||||
@PostMapping("/reservations/{reservationId}/cancel")
|
||||
override fun cancelReservation(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable reservationId: Long,
|
||||
@Valid @RequestBody request: ReservationCancelRequest
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
reservationService.cancelReservation(memberId, reservationId, request)
|
||||
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
|
||||
@GetMapping("/reservations/summary")
|
||||
override fun findSummaryByMemberId(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<MyReservationRetrieveListResponse>> {
|
||||
val response: MyReservationRetrieveListResponse = reservationFindService.findReservationsByMemberId(memberId)
|
||||
): ResponseEntity<CommonApiResponse<ReservationSummaryRetrieveListResponse>> {
|
||||
val response = reservationService.findSummaryByMemberId(memberId)
|
||||
|
||||
return ResponseEntity.ok(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@GetMapping("/reservations/search")
|
||||
override fun searchReservations(
|
||||
@RequestParam(required = false) themeId: Long?,
|
||||
@RequestParam(required = false) memberId: Long?,
|
||||
@RequestParam(required = false) dateFrom: LocalDate?,
|
||||
@RequestParam(required = false) dateTo: LocalDate?
|
||||
): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
|
||||
val response: ReservationRetrieveListResponse = reservationFindService.searchReservations(
|
||||
themeId,
|
||||
memberId,
|
||||
dateFrom,
|
||||
dateTo
|
||||
)
|
||||
@GetMapping("/reservations/{id}/detail")
|
||||
override fun findDetailById(
|
||||
@PathVariable("id") id: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationDetailRetrieveResponse>> {
|
||||
val response = reservationService.findDetailById(id)
|
||||
|
||||
return ResponseEntity.ok(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@DeleteMapping("/reservations/{id}")
|
||||
override fun cancelReservationByAdmin(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
if (reservationWithPaymentService.isNotPaidReservation(reservationId)) {
|
||||
reservationWriteService.deleteReservation(reservationId, memberId)
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
|
||||
val paymentCancelRequest = reservationWithPaymentService.deleteReservationAndPayment(reservationId, memberId)
|
||||
val paymentCancelResponse = paymentClient.cancel(paymentCancelRequest)
|
||||
reservationWithPaymentService.updateCanceledTime(
|
||||
paymentCancelRequest.paymentKey,
|
||||
paymentCancelResponse.canceledAt
|
||||
)
|
||||
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
|
||||
@PostMapping("/reservations")
|
||||
override fun createReservationWithPayment(
|
||||
@Valid @RequestBody reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>> {
|
||||
val paymentRequest: PaymentApproveRequest = reservationCreateWithPaymentRequest.toPaymentApproveRequest()
|
||||
val paymentResponse: PaymentApproveResponse = paymentClient.confirm(paymentRequest)
|
||||
|
||||
try {
|
||||
val response: ReservationCreateResponse =
|
||||
reservationWithPaymentService.createReservationAndPayment(
|
||||
reservationCreateWithPaymentRequest,
|
||||
paymentResponse,
|
||||
memberId
|
||||
)
|
||||
return ResponseEntity.created(URI.create("/reservations/${response.id}"))
|
||||
.body(CommonApiResponse(response))
|
||||
} catch (e: Exception) {
|
||||
val cancelRequest = PaymentCancelRequest(
|
||||
paymentRequest.paymentKey,
|
||||
paymentRequest.amount,
|
||||
e.message!!
|
||||
)
|
||||
val paymentCancelResponse = paymentClient.cancel(cancelRequest)
|
||||
reservationWithPaymentService.createCanceledPayment(
|
||||
paymentCancelResponse,
|
||||
paymentResponse.approvedAt,
|
||||
paymentRequest.paymentKey
|
||||
)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/reservations/admin")
|
||||
override fun createReservationByAdmin(
|
||||
@Valid @RequestBody adminReservationRequest: AdminReservationCreateRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>> {
|
||||
val response: ReservationCreateResponse =
|
||||
reservationWriteService.createReservationByAdmin(adminReservationRequest, memberId)
|
||||
|
||||
return ResponseEntity.created(URI.create("/reservations/${response.id}"))
|
||||
.body(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@GetMapping("/reservations/waiting")
|
||||
override fun findAllWaiting(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
|
||||
val response: ReservationRetrieveListResponse = reservationFindService.findAllWaiting()
|
||||
|
||||
return ResponseEntity.ok(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@PostMapping("/reservations/waiting")
|
||||
override fun createWaiting(
|
||||
@Valid @RequestBody waitingCreateRequest: WaitingCreateRequest,
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
): ResponseEntity<CommonApiResponse<ReservationCreateResponse>> {
|
||||
val response: ReservationCreateResponse = reservationWriteService.createWaiting(
|
||||
waitingCreateRequest,
|
||||
memberId
|
||||
)
|
||||
|
||||
return ResponseEntity.created(URI.create("/reservations/${response.id}"))
|
||||
.body(CommonApiResponse(response))
|
||||
}
|
||||
|
||||
@DeleteMapping("/reservations/waiting/{id}")
|
||||
override fun cancelWaitingByMember(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
reservationWriteService.deleteWaiting(reservationId, memberId)
|
||||
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
|
||||
@PostMapping("/reservations/waiting/{id}/confirm")
|
||||
override fun confirmWaiting(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
reservationWriteService.confirmWaiting(reservationId, memberId)
|
||||
|
||||
return ResponseEntity.ok().build()
|
||||
}
|
||||
|
||||
@PostMapping("/reservations/waiting/{id}/reject")
|
||||
override fun rejectWaiting(
|
||||
@MemberId @Parameter(hidden = true) memberId: Long,
|
||||
@PathVariable("id") reservationId: Long
|
||||
): ResponseEntity<CommonApiResponse<Unit>> {
|
||||
reservationWriteService.deleteWaiting(reservationId, memberId)
|
||||
|
||||
return ResponseEntity.noContent().build()
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user