160 lines
6.8 KiB
Kotlin

package roomescape.reservation.web
import io.swagger.v3.oas.annotations.Parameter
import jakarta.validation.Valid
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.common.exception.RoomescapeException
import roomescape.payment.infrastructure.client.TossPaymentClient
import roomescape.payment.web.PaymentApprove
import roomescape.payment.web.PaymentCancel
import roomescape.reservation.business.ReservationService
import roomescape.reservation.business.ReservationWithPaymentService
import roomescape.reservation.docs.ReservationAPI
import java.net.URI
import java.time.LocalDate
@RestController
class ReservationController(
private val reservationWithPaymentService: ReservationWithPaymentService,
private val reservationService: ReservationService,
private val paymentClient: TossPaymentClient
) : ReservationAPI {
@GetMapping("/reservations")
override fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationsResponse>> {
val response: ReservationsResponse = reservationService.findAllReservations()
return ResponseEntity.ok(CommonApiResponse(response))
}
@GetMapping("/reservations-mine")
override fun getMemberReservations(
@MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<MyReservationsResponse>> {
val response: MyReservationsResponse = reservationService.findMemberReservations(memberId)
return ResponseEntity.ok(CommonApiResponse(response))
}
@GetMapping("/reservations/search")
override fun getReservationBySearching(
@RequestParam(required = false) themeId: Long?,
@RequestParam(required = false) memberId: Long?,
@RequestParam(required = false) dateFrom: LocalDate?,
@RequestParam(required = false) dateTo: LocalDate?
): ResponseEntity<CommonApiResponse<ReservationsResponse>> {
val response: ReservationsResponse = reservationService.findFilteredReservations(themeId, memberId, dateFrom, dateTo)
return ResponseEntity.ok(CommonApiResponse(response))
}
@DeleteMapping("/reservations/{id}")
override fun removeReservation(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>> {
if (reservationWithPaymentService.isNotPaidReservation(reservationId)) {
reservationService.removeReservationById(reservationId, memberId)
return ResponseEntity.noContent().build()
}
val paymentCancelRequest = reservationWithPaymentService.removeReservationWithPayment(
reservationId, memberId)
val paymentCancelResponse = paymentClient.cancelPayment(paymentCancelRequest)
reservationWithPaymentService.updateCanceledTime(paymentCancelRequest.paymentKey,
paymentCancelResponse.canceledAt)
return ResponseEntity.noContent().build()
}
@PostMapping("/reservations")
override fun saveReservation(
@Valid @RequestBody reservationRequest: ReservationRequest,
@MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<ReservationResponse>> {
val paymentRequest: PaymentApprove.Request = reservationRequest.paymentRequest
val paymentResponse: PaymentApprove.Response = paymentClient.confirmPayment(paymentRequest)
try {
val reservationResponse: ReservationResponse = reservationWithPaymentService.addReservationWithPayment(
reservationRequest,
paymentResponse,
memberId
)
return ResponseEntity.created(URI.create("/reservations/${reservationResponse.id}"))
.body(CommonApiResponse(reservationResponse))
} catch (e: RoomescapeException) {
val cancelRequest = PaymentCancel.Request(paymentRequest.paymentKey,
paymentRequest.amount, e.message!!)
val paymentCancelResponse = paymentClient.cancelPayment(cancelRequest)
reservationWithPaymentService.saveCanceledPayment(paymentCancelResponse, paymentResponse.approvedAt,
paymentRequest.paymentKey)
throw e
}
}
@PostMapping("/reservations/admin")
override fun saveReservationByAdmin(
@Valid @RequestBody adminReservationRequest: AdminReservationRequest
): ResponseEntity<CommonApiResponse<ReservationResponse>> {
val response: ReservationResponse =
reservationService.addReservationByAdmin(adminReservationRequest)
return ResponseEntity.created(URI.create("/reservations/${response.id}"))
.body(CommonApiResponse(response))
}
@GetMapping("/reservations/waiting")
override fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationsResponse>> {
val response: ReservationsResponse = reservationService.findAllWaiting()
return ResponseEntity.ok(CommonApiResponse(response))
}
@PostMapping("/reservations/waiting")
override fun saveWaiting(
@Valid @RequestBody waitingRequest: WaitingRequest,
@MemberId @Parameter(hidden = true) memberId: Long,
): ResponseEntity<CommonApiResponse<ReservationResponse>> {
val response: ReservationResponse = reservationService.addWaiting(
waitingRequest,
memberId
)
return ResponseEntity.created(URI.create("/reservations/${response.id}"))
.body(CommonApiResponse(response))
}
@DeleteMapping("/reservations/waiting/{id}")
override fun deleteWaiting(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>> {
reservationService.cancelWaiting(reservationId, memberId)
return ResponseEntity.noContent().build()
}
@PostMapping("/reservations/waiting/{id}/approve")
override fun approveWaiting(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>> {
reservationService.approveWaiting(reservationId, memberId)
return ResponseEntity.ok().build()
}
@PostMapping("/reservations/waiting/{id}/deny")
override fun denyWaiting(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>> {
reservationService.denyWaiting(reservationId, memberId)
return ResponseEntity.noContent().build()
}
}