[#16] Reservation 도메인 코드 코틀린 마이그레이션 #17

Merged
pricelees merged 40 commits from refactor/#16 into main 2025-07-21 12:08:56 +00:00
2 changed files with 271 additions and 239 deletions
Showing only changes of commit eb7461e9b6 - Show all commits

View File

@ -0,0 +1,138 @@
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
@Tag(name = "3. 예약 API", description = "예약 및 대기 정보를 추가 / 조회 / 삭제할 때 사용합니다.")
interface ReservationAPI {
@Admin
@Operation(summary = "모든 예약 정보 조회", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationsResponse>>
@LoginRequired
@Operation(summary = "자신의 예약 및 대기 조회", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getMemberReservations(
@MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<MyReservationsResponse>>
@Admin
@Operation(summary = "관리자의 예약 검색", description = "특정 조건에 해당되는 예약 검색", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(
ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)
)
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>>
@Admin
@Operation(summary = "관리자의 예약 취소", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(
ApiResponse(responseCode = "204", description = "성공"),
)
fun removeReservation(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") reservationId: 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 saveReservation(
@Valid @RequestBody reservationRequest: ReservationRequest,
@MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<ReservationResponse>>
@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 saveReservationByAdmin(
@Valid @RequestBody adminReservationRequest: AdminReservationRequest,
): ResponseEntity<CommonApiResponse<ReservationResponse>>
@Admin
@Operation(summary = "모든 예약 대기 조회", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationsResponse>>
@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 saveWaiting(
@Valid @RequestBody waitingRequest: WaitingRequest,
@MemberId @Parameter(hidden = true) memberId: Long,
): ResponseEntity<CommonApiResponse<ReservationResponse>>
@LoginRequired
@Operation(summary = "예약 대기 취소", tags = ["로그인이 필요한 API"])
@ApiResponses(
ApiResponse(responseCode = "204", description = "성공"),
)
fun deleteWaiting(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") @Parameter(description = "예약 ID") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>>
@Admin
@Operation(summary = "대기 중인 예약 승인", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(
ApiResponse(responseCode = "200", description = "성공"),
)
fun approveWaiting(
@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 denyWaiting(
@MemberId @Parameter(hidden = true) memberId: Long,
@PathVariable("id") @Parameter(description = "예약 ID") reservationId: Long
): ResponseEntity<CommonApiResponse<Unit>>
}

View File

@ -1,265 +1,159 @@
package roomescape.reservation.web; package roomescape.reservation.web
import java.time.LocalDate; import io.swagger.v3.oas.annotations.Parameter
import jakarta.validation.Valid
import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity
import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.DeleteMapping; import roomescape.auth.web.support.MemberId
import org.springframework.web.bind.annotation.GetMapping; import roomescape.common.dto.response.CommonApiResponse
import org.springframework.web.bind.annotation.PathVariable; import roomescape.common.exception.RoomescapeException
import org.springframework.web.bind.annotation.PostMapping; import roomescape.payment.infrastructure.client.TossPaymentClient
import org.springframework.web.bind.annotation.RequestBody; import roomescape.payment.web.PaymentApprove
import org.springframework.web.bind.annotation.RequestParam; import roomescape.payment.web.PaymentCancel
import org.springframework.web.bind.annotation.ResponseStatus; import roomescape.reservation.business.ReservationService
import org.springframework.web.bind.annotation.RestController; import roomescape.reservation.business.ReservationWithPaymentService
import roomescape.reservation.docs.ReservationAPI
import io.swagger.v3.oas.annotations.Operation; import java.net.URI
import io.swagger.v3.oas.annotations.Parameter; import java.time.LocalDate
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.media.Content;
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.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import roomescape.auth.web.support.Admin;
import roomescape.auth.web.support.LoginRequired;
import roomescape.auth.web.support.MemberId;
import roomescape.common.dto.response.RoomescapeApiResponse;
import roomescape.common.dto.response.RoomescapeErrorResponse;
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;
@RestController @RestController
@Tag(name = "3. 예약 API", description = "예약 및 대기 정보를 추가 / 조회 / 삭제할 때 사용합니다.") class ReservationController(
public 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()
private final ReservationWithPaymentService reservationWithPaymentService; return ResponseEntity.ok(CommonApiResponse(response))
private final ReservationService reservationService; }
private final TossPaymentClient paymentClient;
public ReservationController(ReservationWithPaymentService reservationWithPaymentService, @GetMapping("/reservations-mine")
ReservationService reservationService, TossPaymentClient paymentClient) { override fun getMemberReservations(
this.reservationWithPaymentService = reservationWithPaymentService; @MemberId @Parameter(hidden = true) memberId: Long
this.reservationService = reservationService; ): ResponseEntity<CommonApiResponse<MyReservationsResponse>> {
this.paymentClient = paymentClient; val response: MyReservationsResponse = reservationService.findMemberReservations(memberId)
}
@Admin return ResponseEntity.ok(CommonApiResponse(response))
@GetMapping("/reservations") }
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "모든 예약 정보 조회", tags = "관리자 로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)
})
public RoomescapeApiResponse<ReservationsResponse> getAllReservations() {
return RoomescapeApiResponse.success(reservationService.findAllReservations());
}
@LoginRequired @GetMapping("/reservations/search")
@GetMapping("/reservations-mine") override fun getReservationBySearching(
@ResponseStatus(HttpStatus.OK) @RequestParam(required = false) themeId: Long?,
@Operation(summary = "자신의 예약 및 대기 조회", tags = "로그인이 필요한 API") @RequestParam(required = false) memberId: Long?,
@ApiResponses({ @RequestParam(required = false) dateFrom: LocalDate?,
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true) @RequestParam(required = false) dateTo: LocalDate?
}) ): ResponseEntity<CommonApiResponse<ReservationsResponse>> {
public RoomescapeApiResponse<MyReservationsResponse> getMemberReservations( val response: ReservationsResponse = reservationService.findFilteredReservations(themeId, memberId, dateFrom, dateTo)
@MemberId @Parameter(hidden = true) Long memberId) {
return RoomescapeApiResponse.success(reservationService.findMemberReservations(memberId));
}
@Admin return ResponseEntity.ok(CommonApiResponse(response))
@GetMapping("/reservations/search") }
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "관리자의 예약 검색", description = "특정 조건에 해당되는 예약 검색", tags = "관리자 로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true),
@ApiResponse(responseCode = "400", description = "날짜 범위를 지정할 때, 종료 날짜는 시작 날짜 이전일 수 없습니다.",
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
})
public RoomescapeApiResponse<ReservationsResponse> getReservationBySearching(
@RequestParam(required = false) @Parameter(description = "테마 ID") Long themeId,
@RequestParam(required = false) @Parameter(description = "회원 ID") Long memberId,
@RequestParam(required = false) @Parameter(description = "yyyy-MM-dd 형식으로 입력해주세요", example = "2024-06-10") LocalDate dateFrom,
@RequestParam(required = false) @Parameter(description = "yyyy-MM-dd 형식으로 입력해주세요", example = "2024-06-10") LocalDate dateTo
) {
return RoomescapeApiResponse.success(
reservationService.findFilteredReservations(themeId, memberId, dateFrom, dateTo));
}
@Admin @DeleteMapping("/reservations/{id}")
@DeleteMapping("/reservations/{id}") override fun removeReservation(
@ResponseStatus(HttpStatus.NO_CONTENT) @MemberId @Parameter(hidden = true) memberId: Long,
@Operation(summary = "관리자의 예약 취소", tags = "관리자 로그인이 필요한 API") @PathVariable("id") reservationId: Long
@ApiResponses({ ): ResponseEntity<CommonApiResponse<Unit>> {
@ApiResponse(responseCode = "204", description = "성공"), if (reservationWithPaymentService.isNotPaidReservation(reservationId)) {
@ApiResponse(responseCode = "404", description = "예약 또는 결제 정보를 찾을 수 없습니다.", reservationService.removeReservationById(reservationId, memberId)
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class))), return ResponseEntity.noContent().build()
}) }
public RoomescapeApiResponse<Void> removeReservation(
@MemberId @Parameter(hidden = true) Long memberId,
@NotNull(message = "reservationId는 null일 수 없습니다.") @PathVariable("id") @Parameter(description = "예약 ID") Long reservationId
) {
if (reservationWithPaymentService.isNotPaidReservation(reservationId)) { val paymentCancelRequest = reservationWithPaymentService.removeReservationWithPayment(
reservationService.removeReservationById(reservationId, memberId); reservationId, memberId)
return RoomescapeApiResponse.success(); val paymentCancelResponse = paymentClient.cancelPayment(paymentCancelRequest)
} reservationWithPaymentService.updateCanceledTime(paymentCancelRequest.paymentKey,
paymentCancelResponse.canceledAt)
PaymentCancel.Request paymentCancelRequest = reservationWithPaymentService.removeReservationWithPayment( return ResponseEntity.noContent().build()
reservationId, memberId); }
PaymentCancel.Response paymentCancelResponse = paymentClient.cancelPayment(paymentCancelRequest); @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)
reservationWithPaymentService.updateCanceledTime(paymentCancelRequest.paymentKey, try {
paymentCancelResponse.canceledAt); 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
}
}
return RoomescapeApiResponse.success(); @PostMapping("/reservations/admin")
} override fun saveReservationByAdmin(
@Valid @RequestBody adminReservationRequest: AdminReservationRequest
): ResponseEntity<CommonApiResponse<ReservationResponse>> {
val response: ReservationResponse =
reservationService.addReservationByAdmin(adminReservationRequest)
@LoginRequired return ResponseEntity.created(URI.create("/reservations/${response.id}"))
@PostMapping("/reservations") .body(CommonApiResponse(response))
@ResponseStatus(HttpStatus.CREATED) }
@Operation(summary = "예약 추가", tags = "로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true,
headers = @Header(name = HttpHeaders.LOCATION, description = "생성된 예약 정보 URL", schema = @Schema(example = "/reservations/1")))
})
public RoomescapeApiResponse<ReservationResponse> saveReservation(
@Valid @RequestBody ReservationRequest reservationRequest,
@MemberId @Parameter(hidden = true) Long memberId,
HttpServletResponse response
) {
PaymentApprove.Request paymentRequest = reservationRequest.paymentRequest();
PaymentApprove.Response paymentResponse = paymentClient.confirmPayment(paymentRequest);
try { @GetMapping("/reservations/waiting")
ReservationResponse reservationResponse = reservationWithPaymentService.addReservationWithPayment( override fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationsResponse>> {
reservationRequest, paymentResponse, memberId); val response: ReservationsResponse = reservationService.findAllWaiting()
return getCreatedReservationResponse(reservationResponse, response);
} catch (RoomescapeException e) {
PaymentCancel.Request cancelRequest = new PaymentCancel.Request(paymentRequest.paymentKey,
paymentRequest.amount, e.getMessage());
PaymentCancel.Response paymentCancelResponse = paymentClient.cancelPayment(cancelRequest); return ResponseEntity.ok(CommonApiResponse(response))
}
reservationWithPaymentService.saveCanceledPayment(paymentCancelResponse, paymentResponse.approvedAt, @PostMapping("/reservations/waiting")
paymentRequest.paymentKey); override fun saveWaiting(
throw e; @Valid @RequestBody waitingRequest: WaitingRequest,
} @MemberId @Parameter(hidden = true) memberId: Long,
} ): ResponseEntity<CommonApiResponse<ReservationResponse>> {
val response: ReservationResponse = reservationService.addWaiting(
waitingRequest,
memberId
)
@Admin return ResponseEntity.created(URI.create("/reservations/${response.id}"))
@PostMapping("/reservations/admin") .body(CommonApiResponse(response))
@ResponseStatus(HttpStatus.CREATED) }
@Operation(summary = "관리자 예약 추가", tags = "관리자 로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true,
headers = @Header(name = HttpHeaders.LOCATION, description = "생성된 예약 정보 URL", schema = @Schema(example = "/reservations/1"))),
@ApiResponse(responseCode = "409", description = "예약이 이미 존재합니다.", content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
})
public RoomescapeApiResponse<ReservationResponse> saveReservationByAdmin(
@Valid @RequestBody AdminReservationRequest adminReservationRequest,
HttpServletResponse response
) {
ReservationResponse reservationResponse = reservationService.addReservationByAdmin(adminReservationRequest);
return getCreatedReservationResponse(reservationResponse, response);
}
@Admin @DeleteMapping("/reservations/waiting/{id}")
@GetMapping("/reservations/waiting") override fun deleteWaiting(
@ResponseStatus(HttpStatus.OK) @MemberId @Parameter(hidden = true) memberId: Long,
@Operation(summary = "모든 예약 대기 조회", tags = "관리자 로그인이 필요한 API") @PathVariable("id") reservationId: Long
@ApiResponses({ ): ResponseEntity<CommonApiResponse<Unit>> {
@ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true) reservationService.cancelWaiting(reservationId, memberId)
})
public RoomescapeApiResponse<ReservationsResponse> getAllWaiting() {
return RoomescapeApiResponse.success(reservationService.findAllWaiting());
}
@LoginRequired return ResponseEntity.noContent().build()
@PostMapping("/reservations/waiting") }
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "예약 대기 신청", tags = "로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true,
headers = @Header(name = HttpHeaders.LOCATION, description = "생성된 예약 정보 URL", schema = @Schema(example = "/reservations/1")))
})
public RoomescapeApiResponse<ReservationResponse> saveWaiting(
@Valid @RequestBody WaitingRequest waitingRequest,
@MemberId @Parameter(hidden = true) Long memberId,
HttpServletResponse response
) {
ReservationResponse reservationResponse = reservationService.addWaiting(waitingRequest, memberId);
return getCreatedReservationResponse(reservationResponse, response);
}
@LoginRequired @PostMapping("/reservations/waiting/{id}/approve")
@DeleteMapping("/reservations/waiting/{id}") override fun approveWaiting(
@ResponseStatus(HttpStatus.NO_CONTENT) @MemberId @Parameter(hidden = true) memberId: Long,
@Operation(summary = "예약 대기 취소", tags = "로그인이 필요한 API") @PathVariable("id") reservationId: Long
@ApiResponses({ ): ResponseEntity<CommonApiResponse<Unit>> {
@ApiResponse(responseCode = "204", description = "성공"), reservationService.approveWaiting(reservationId, memberId)
@ApiResponse(responseCode = "404", description = "회원의 예약 대기 정보를 찾을 수 없습니다.",
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
})
public RoomescapeApiResponse<Void> deleteWaiting(
@MemberId @Parameter(hidden = true) Long memberId,
@NotNull(message = "reservationId는 null 또는 공백일 수 없습니다.") @PathVariable("id") @Parameter(description = "예약 ID") Long reservationId
) {
reservationService.cancelWaiting(reservationId, memberId);
return RoomescapeApiResponse.success();
}
@Admin return ResponseEntity.ok().build()
@PostMapping("/reservations/waiting/{id}/approve") }
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "대기 중인 예약 승인", tags = "관리자 로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "성공"),
@ApiResponse(responseCode = "404", description = "예약 대기 정보를 찾을 수 없습니다.",
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class))),
@ApiResponse(responseCode = "409", description = "확정된 예약이 존재하여 대기 중인 예약을 승인할 수 없습니다.",
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
})
public RoomescapeApiResponse<Void> approveWaiting(
@MemberId @Parameter(hidden = true) Long memberId,
@NotNull(message = "reservationId는 null 또는 공백일 수 없습니다.") @PathVariable("id") @Parameter(description = "예약 ID") Long reservationId
) {
reservationService.approveWaiting(reservationId, memberId);
return RoomescapeApiResponse.success(); @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)
@Admin return ResponseEntity.noContent().build()
@PostMapping("/reservations/waiting/{id}/deny") }
@ResponseStatus(HttpStatus.NO_CONTENT)
@Operation(summary = "대기 중인 예약 거절", tags = "관리자 로그인이 필요한 API")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "대기 중인 예약 거절 성공"),
@ApiResponse(responseCode = "404", description = "예약 대기 정보를 찾을 수 없습니다.",
content = @Content(schema = @Schema(implementation = RoomescapeErrorResponse.class)))
})
public RoomescapeApiResponse<Void> denyWaiting(
@MemberId @Parameter(hidden = true) Long memberId,
@NotNull(message = "reservationId는 null 또는 공백일 수 없습니다.") @PathVariable("id") @Parameter(description = "예약 ID") Long reservationId
) {
reservationService.denyWaiting(reservationId, memberId);
return RoomescapeApiResponse.success();
}
private RoomescapeApiResponse<ReservationResponse> getCreatedReservationResponse(
ReservationResponse reservationResponse,
HttpServletResponse response
) {
response.setHeader(HttpHeaders.LOCATION, "/reservations/" + reservationResponse.id);
return RoomescapeApiResponse.success(reservationResponse);
}
} }