[#18] 코드 정리 및 일부 컨벤션 통일 #19

Merged
pricelees merged 24 commits from refactor/#18 into main 2025-07-22 09:05:31 +00:00
14 changed files with 108 additions and 154 deletions
Showing only changes of commit 35981f53ad - Show all commits

View File

@ -29,7 +29,7 @@ class PaymentService(
): PaymentCreateResponse = PaymentEntity( ): PaymentCreateResponse = PaymentEntity(
orderId = paymentResponse.orderId, orderId = paymentResponse.orderId,
paymentKey = paymentResponse.paymentKey, paymentKey = paymentResponse.paymentKey,
totalAmount = paymentResponse.amount, totalAmount = paymentResponse.totalAmount,
reservation = reservation, reservation = reservation,
approvedAt = paymentResponse.approvedAt approvedAt = paymentResponse.approvedAt
).also { ).also {

View File

@ -3,8 +3,8 @@ package roomescape.payment.web
import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import roomescape.payment.infrastructure.client.PaymentCancelResponseDeserializer import roomescape.payment.infrastructure.client.PaymentCancelResponseDeserializer
import roomescape.payment.infrastructure.persistence.PaymentEntity import roomescape.payment.infrastructure.persistence.PaymentEntity
import roomescape.reservation.web.ReservationResponse import roomescape.reservation.web.ReservationRetrieveResponse
import roomescape.reservation.web.toCreateResponse import roomescape.reservation.web.toRetrieveResponse
import java.time.OffsetDateTime import java.time.OffsetDateTime
data class PaymentCancelRequest( data class PaymentCancelRequest(
@ -26,7 +26,7 @@ data class PaymentCreateResponse(
val orderId: String, val orderId: String,
val paymentKey: String, val paymentKey: String,
val totalAmount: Long, val totalAmount: Long,
val reservation: ReservationResponse, val reservation: ReservationRetrieveResponse,
val approvedAt: OffsetDateTime val approvedAt: OffsetDateTime
) )
@ -35,6 +35,6 @@ fun PaymentEntity.toCreateResponse(): PaymentCreateResponse = PaymentCreateRespo
orderId = this.orderId, orderId = this.orderId,
paymentKey = this.paymentKey, paymentKey = this.paymentKey,
totalAmount = this.totalAmount, totalAmount = this.totalAmount,
reservation = this.reservation.toCreateResponse(), reservation = this.reservation.toRetrieveResponse(),
approvedAt = this.approvedAt approvedAt = this.approvedAt
) )

View File

@ -24,26 +24,26 @@ class ReservationService(
) { ) {
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findAllReservations(): ReservationsResponse { fun findAllReservations(): ReservationRetrieveListResponse {
val spec: Specification<ReservationEntity> = ReservationSearchSpecification() val spec: Specification<ReservationEntity> = ReservationSearchSpecification()
.confirmed() .confirmed()
.build() .build()
return ReservationsResponse(findAllReservationByStatus(spec)) return ReservationRetrieveListResponse(findAllReservationByStatus(spec))
} }
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findAllWaiting(): ReservationsResponse { fun findAllWaiting(): ReservationRetrieveListResponse {
val spec: Specification<ReservationEntity> = ReservationSearchSpecification() val spec: Specification<ReservationEntity> = ReservationSearchSpecification()
.waiting() .waiting()
.build() .build()
return ReservationsResponse(findAllReservationByStatus(spec)) return ReservationRetrieveListResponse(findAllReservationByStatus(spec))
} }
private fun findAllReservationByStatus(spec: Specification<ReservationEntity>): List<ReservationResponse> { private fun findAllReservationByStatus(spec: Specification<ReservationEntity>): List<ReservationRetrieveResponse> {
return reservationRepository.findAll(spec).map { it.toCreateResponse() } return reservationRepository.findAll(spec).map { it.toRetrieveResponse() }
} }
fun removeReservationById(reservationId: Long, memberId: Long) { fun removeReservationById(reservationId: Long, memberId: Long) {
@ -51,7 +51,7 @@ class ReservationService(
reservationRepository.deleteById(reservationId) reservationRepository.deleteById(reservationId)
} }
fun addReservation(request: ReservationRequest, memberId: Long): ReservationEntity { fun addReservation(request: ReservationCreateWithPaymentRequest, memberId: Long): ReservationEntity {
validateIsReservationExist(request.themeId, request.timeId, request.date) validateIsReservationExist(request.themeId, request.timeId, request.date)
return getReservationForSave( return getReservationForSave(
request.timeId, request.timeId,
@ -64,7 +64,7 @@ class ReservationService(
} }
} }
fun addReservationByAdmin(request: AdminReservationRequest): ReservationResponse { fun addReservationByAdmin(request: AdminReservationCreateRequest): ReservationRetrieveResponse {
validateIsReservationExist(request.themeId, request.timeId, request.date) validateIsReservationExist(request.themeId, request.timeId, request.date)
return addReservationWithoutPayment( return addReservationWithoutPayment(
@ -76,7 +76,7 @@ class ReservationService(
) )
} }
fun addWaiting(request: WaitingRequest, memberId: Long): ReservationResponse { fun addWaiting(request: WaitingCreateRequest, memberId: Long): ReservationRetrieveResponse {
validateMemberAlreadyReserve(request.themeId, request.timeId, request.date, memberId) validateMemberAlreadyReserve(request.themeId, request.timeId, request.date, memberId)
return addReservationWithoutPayment( return addReservationWithoutPayment(
request.themeId, request.themeId,
@ -93,10 +93,10 @@ class ReservationService(
date: LocalDate, date: LocalDate,
memberId: Long, memberId: Long,
status: ReservationStatus status: ReservationStatus
): ReservationResponse = getReservationForSave(timeId, themeId, date, memberId, status) ): ReservationRetrieveResponse = getReservationForSave(timeId, themeId, date, memberId, status)
.also { .also {
reservationRepository.save(it) reservationRepository.save(it)
}.toCreateResponse() }.toRetrieveResponse()
private fun validateMemberAlreadyReserve(themeId: Long?, timeId: Long?, date: LocalDate?, memberId: Long?) { private fun validateMemberAlreadyReserve(themeId: Long?, timeId: Long?, date: LocalDate?, memberId: Long?) {
@ -169,7 +169,7 @@ class ReservationService(
memberId: Long?, memberId: Long?,
dateFrom: LocalDate?, dateFrom: LocalDate?,
dateTo: LocalDate? dateTo: LocalDate?
): ReservationsResponse { ): ReservationRetrieveListResponse {
validateDateForSearch(dateFrom, dateTo) validateDateForSearch(dateFrom, dateTo)
val spec: Specification<ReservationEntity> = ReservationSearchSpecification() val spec: Specification<ReservationEntity> = ReservationSearchSpecification()
.confirmed() .confirmed()
@ -179,7 +179,7 @@ class ReservationService(
.dateEndAt(dateTo) .dateEndAt(dateTo)
.build() .build()
return ReservationsResponse(findAllReservationByStatus(spec)) return ReservationRetrieveListResponse(findAllReservationByStatus(spec))
} }
private fun validateDateForSearch(startFrom: LocalDate?, endAt: LocalDate?) { private fun validateDateForSearch(startFrom: LocalDate?, endAt: LocalDate?) {
@ -195,8 +195,8 @@ class ReservationService(
} }
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findMemberReservations(memberId: Long): MyReservationsResponse { fun findMemberReservations(memberId: Long): MyReservationRetrieveListResponse {
return MyReservationsResponse(reservationRepository.findMyReservations(memberId)) return MyReservationRetrieveListResponse(reservationRepository.findMyReservations(memberId))
} }
fun approveWaiting(reservationId: Long, memberId: Long) { fun approveWaiting(reservationId: Long, memberId: Long) {

View File

@ -7,8 +7,8 @@ import roomescape.payment.infrastructure.client.PaymentApproveResponse
import roomescape.payment.web.PaymentCancelRequest import roomescape.payment.web.PaymentCancelRequest
import roomescape.payment.web.PaymentCancelResponse import roomescape.payment.web.PaymentCancelResponse
import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.web.ReservationRequest import roomescape.reservation.web.ReservationCreateWithPaymentRequest
import roomescape.reservation.web.ReservationResponse import roomescape.reservation.web.ReservationRetrieveResponse
import java.time.OffsetDateTime import java.time.OffsetDateTime
@Service @Service
@ -18,10 +18,10 @@ class ReservationWithPaymentService(
private val paymentService: PaymentService private val paymentService: PaymentService
) { ) {
fun addReservationWithPayment( fun addReservationWithPayment(
request: ReservationRequest, request: ReservationCreateWithPaymentRequest,
paymentInfo: PaymentApproveResponse, paymentInfo: PaymentApproveResponse,
memberId: Long memberId: Long
): ReservationResponse { ): ReservationRetrieveResponse {
val reservation: ReservationEntity = reservationService.addReservation(request, memberId) val reservation: ReservationEntity = reservationService.addReservation(request, memberId)
return paymentService.createPayment(paymentInfo, reservation) return paymentService.createPayment(paymentInfo, reservation)

View File

@ -26,14 +26,14 @@ interface ReservationAPI {
@Admin @Admin
@Operation(summary = "모든 예약 정보 조회", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "모든 예약 정보 조회", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationsResponse>> fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
@LoginRequired @LoginRequired
@Operation(summary = "자신의 예약 및 대기 조회", tags = ["로그인이 필요한 API"]) @Operation(summary = "자신의 예약 및 대기 조회", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getMemberReservations( fun getMemberReservations(
@MemberId @Parameter(hidden = true) memberId: Long @MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<MyReservationsResponse>> ): ResponseEntity<CommonApiResponse<MyReservationRetrieveListResponse>>
@Admin @Admin
@Operation(summary = "관리자의 예약 검색", description = "특정 조건에 해당되는 예약 검색", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "관리자의 예약 검색", description = "특정 조건에 해당되는 예약 검색", tags = ["관리자 로그인이 필요한 API"])
@ -45,7 +45,7 @@ interface ReservationAPI {
@RequestParam(required = false) memberId: Long?, @RequestParam(required = false) memberId: Long?,
@RequestParam(required = false) dateFrom: LocalDate?, @RequestParam(required = false) dateFrom: LocalDate?,
@RequestParam(required = false) dateTo: LocalDate? @RequestParam(required = false) dateTo: LocalDate?
): ResponseEntity<CommonApiResponse<ReservationsResponse>> ): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
@Admin @Admin
@Operation(summary = "관리자의 예약 취소", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "관리자의 예약 취소", tags = ["관리자 로그인이 필요한 API"])
@ -68,9 +68,9 @@ interface ReservationAPI {
) )
) )
fun saveReservation( fun saveReservation(
@Valid @RequestBody reservationRequest: ReservationRequest, @Valid @RequestBody reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest,
@MemberId @Parameter(hidden = true) memberId: Long @MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<ReservationResponse>> ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>>
@Admin @Admin
@Operation(summary = "관리자 예약 추가", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "관리자 예약 추가", tags = ["관리자 로그인이 필요한 API"])
@ -83,13 +83,13 @@ interface ReservationAPI {
) )
) )
fun saveReservationByAdmin( fun saveReservationByAdmin(
@Valid @RequestBody adminReservationRequest: AdminReservationRequest, @Valid @RequestBody adminReservationRequest: AdminReservationCreateRequest,
): ResponseEntity<CommonApiResponse<ReservationResponse>> ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>>
@Admin @Admin
@Operation(summary = "모든 예약 대기 조회", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "모든 예약 대기 조회", tags = ["관리자 로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationsResponse>> fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>>
@LoginRequired @LoginRequired
@Operation(summary = "예약 대기 신청", tags = ["로그인이 필요한 API"]) @Operation(summary = "예약 대기 신청", tags = ["로그인이 필요한 API"])
@ -102,9 +102,9 @@ interface ReservationAPI {
) )
) )
fun saveWaiting( fun saveWaiting(
@Valid @RequestBody waitingRequest: WaitingRequest, @Valid @RequestBody waitingCreateRequest: WaitingCreateRequest,
@MemberId @Parameter(hidden = true) memberId: Long, @MemberId @Parameter(hidden = true) memberId: Long,
): ResponseEntity<CommonApiResponse<ReservationResponse>> ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>>
@LoginRequired @LoginRequired
@Operation(summary = "예약 대기 취소", tags = ["로그인이 필요한 API"]) @Operation(summary = "예약 대기 취소", tags = ["로그인이 필요한 API"])

View File

@ -5,7 +5,7 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor
import org.springframework.data.jpa.repository.Modifying import org.springframework.data.jpa.repository.Modifying
import org.springframework.data.jpa.repository.Query import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param import org.springframework.data.repository.query.Param
import roomescape.reservation.web.MyReservationResponse import roomescape.reservation.web.MyReservationRetrieveResponse
import java.time.LocalDate import java.time.LocalDate
interface ReservationRepository interface ReservationRepository
@ -42,7 +42,7 @@ interface ReservationRepository
fun isExistConfirmedReservation(@Param("id") reservationId: Long): Boolean fun isExistConfirmedReservation(@Param("id") reservationId: Long): Boolean
@Query(""" @Query("""
SELECT new roomescape.reservation.web.MyReservationResponse( SELECT new roomescape.reservation.web.MyReservationRetrieveResponse(
r.id, r.id,
t.name, t.name,
r.date, r.date,
@ -58,5 +58,5 @@ interface ReservationRepository
ON p.reservation = r ON p.reservation = r
WHERE r.member.id = :memberId WHERE r.member.id = :memberId
""") """)
fun findMyReservations(memberId: Long): List<MyReservationResponse> fun findMyReservations(memberId: Long): List<MyReservationRetrieveResponse>
} }

View File

@ -24,8 +24,8 @@ class ReservationController(
private val paymentClient: TossPaymentClient private val paymentClient: TossPaymentClient
) : ReservationAPI { ) : ReservationAPI {
@GetMapping("/reservations") @GetMapping("/reservations")
override fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationsResponse>> { override fun getAllReservations(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
val response: ReservationsResponse = reservationService.findAllReservations() val response: ReservationRetrieveListResponse = reservationService.findAllReservations()
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@ -33,8 +33,8 @@ class ReservationController(
@GetMapping("/reservations-mine") @GetMapping("/reservations-mine")
override fun getMemberReservations( override fun getMemberReservations(
@MemberId @Parameter(hidden = true) memberId: Long @MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<MyReservationsResponse>> { ): ResponseEntity<CommonApiResponse<MyReservationRetrieveListResponse>> {
val response: MyReservationsResponse = reservationService.findMemberReservations(memberId) val response: MyReservationRetrieveListResponse = reservationService.findMemberReservations(memberId)
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@ -45,8 +45,8 @@ class ReservationController(
@RequestParam(required = false) memberId: Long?, @RequestParam(required = false) memberId: Long?,
@RequestParam(required = false) dateFrom: LocalDate?, @RequestParam(required = false) dateFrom: LocalDate?,
@RequestParam(required = false) dateTo: LocalDate? @RequestParam(required = false) dateTo: LocalDate?
): ResponseEntity<CommonApiResponse<ReservationsResponse>> { ): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
val response: ReservationsResponse = reservationService.findFilteredReservations(themeId, memberId, dateFrom, dateTo) val response: ReservationRetrieveListResponse = reservationService.findFilteredReservations(themeId, memberId, dateFrom, dateTo)
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@ -72,20 +72,20 @@ class ReservationController(
@PostMapping("/reservations") @PostMapping("/reservations")
override fun saveReservation( override fun saveReservation(
@Valid @RequestBody reservationRequest: ReservationRequest, @Valid @RequestBody reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest,
@MemberId @Parameter(hidden = true) memberId: Long @MemberId @Parameter(hidden = true) memberId: Long
): ResponseEntity<CommonApiResponse<ReservationResponse>> { ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>> {
val paymentRequest: PaymentApproveRequest = reservationRequest.paymentRequest val paymentRequest: PaymentApproveRequest = reservationCreateWithPaymentRequest.toPaymentApproveRequest()
val paymentResponse: PaymentApproveResponse = paymentClient.confirmPayment(paymentRequest) val paymentResponse: PaymentApproveResponse = paymentClient.confirmPayment(paymentRequest)
try { try {
val reservationResponse: ReservationResponse = reservationWithPaymentService.addReservationWithPayment( val reservationRetrieveResponse: ReservationRetrieveResponse = reservationWithPaymentService.addReservationWithPayment(
reservationRequest, reservationCreateWithPaymentRequest,
paymentResponse, paymentResponse,
memberId memberId
) )
return ResponseEntity.created(URI.create("/reservations/${reservationResponse.id}")) return ResponseEntity.created(URI.create("/reservations/${reservationRetrieveResponse.id}"))
.body(CommonApiResponse(reservationResponse)) .body(CommonApiResponse(reservationRetrieveResponse))
} catch (e: RoomescapeException) { } catch (e: RoomescapeException) {
val cancelRequest = PaymentCancelRequest(paymentRequest.paymentKey, val cancelRequest = PaymentCancelRequest(paymentRequest.paymentKey,
paymentRequest.amount, e.message!!) paymentRequest.amount, e.message!!)
@ -98,9 +98,9 @@ class ReservationController(
@PostMapping("/reservations/admin") @PostMapping("/reservations/admin")
override fun saveReservationByAdmin( override fun saveReservationByAdmin(
@Valid @RequestBody adminReservationRequest: AdminReservationRequest @Valid @RequestBody adminReservationRequest: AdminReservationCreateRequest
): ResponseEntity<CommonApiResponse<ReservationResponse>> { ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>> {
val response: ReservationResponse = val response: ReservationRetrieveResponse =
reservationService.addReservationByAdmin(adminReservationRequest) reservationService.addReservationByAdmin(adminReservationRequest)
return ResponseEntity.created(URI.create("/reservations/${response.id}")) return ResponseEntity.created(URI.create("/reservations/${response.id}"))
@ -108,19 +108,19 @@ class ReservationController(
} }
@GetMapping("/reservations/waiting") @GetMapping("/reservations/waiting")
override fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationsResponse>> { override fun getAllWaiting(): ResponseEntity<CommonApiResponse<ReservationRetrieveListResponse>> {
val response: ReservationsResponse = reservationService.findAllWaiting() val response: ReservationRetrieveListResponse = reservationService.findAllWaiting()
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@PostMapping("/reservations/waiting") @PostMapping("/reservations/waiting")
override fun saveWaiting( override fun saveWaiting(
@Valid @RequestBody waitingRequest: WaitingRequest, @Valid @RequestBody waitingCreateRequest: WaitingCreateRequest,
@MemberId @Parameter(hidden = true) memberId: Long, @MemberId @Parameter(hidden = true) memberId: Long,
): ResponseEntity<CommonApiResponse<ReservationResponse>> { ): ResponseEntity<CommonApiResponse<ReservationRetrieveResponse>> {
val response: ReservationResponse = reservationService.addWaiting( val response: ReservationRetrieveResponse = reservationService.addWaiting(
waitingRequest, waitingCreateRequest,
memberId memberId
) )

View File

@ -1,31 +1,19 @@
package roomescape.reservation.web package roomescape.reservation.web
import com.fasterxml.jackson.annotation.JsonIgnore
import io.swagger.v3.oas.annotations.media.Schema import io.swagger.v3.oas.annotations.media.Schema
import roomescape.payment.infrastructure.client.PaymentApproveRequest import roomescape.payment.infrastructure.client.PaymentApproveRequest
import java.time.LocalDate import java.time.LocalDate
@Schema(name = "관리자 예약 저장 요청", description = "관리자의 예약 저장 요청시 사용됩니다.") data class AdminReservationCreateRequest(
data class AdminReservationRequest(
@field:Schema(description = "예약 날짜. 지난 날짜는 지정할 수 없으며, yyyy-MM-dd 형식으로 입력해야 합니다.", type = "string", example = "2022-12-31")
val date: LocalDate, val date: LocalDate,
@field:Schema(description = "예약 시간 ID.", example = "1")
val timeId: Long, val timeId: Long,
@field:Schema(description = "테마 ID", example = "1")
val themeId: Long, val themeId: Long,
@field:Schema(description = "회원 ID", example = "1")
val memberId: Long val memberId: Long
) )
@Schema(name = "회원의 예약 저장 요청", description = "회원의 예약 요청시 사용됩니다.") data class ReservationCreateWithPaymentRequest(
data class ReservationRequest(
@field:Schema(description = "예약 날짜. 지난 날짜는 지정할 수 없으며, yyyy-MM-dd 형식으로 입력해야 합니다.", type = "string", example = "2022-12-31")
val date: LocalDate, val date: LocalDate,
@field:Schema(description = "예약 시간 ID.", example = "1")
val timeId: Long, val timeId: Long,
@field:Schema(description = "테마 ID", example = "1")
val themeId: Long, val themeId: Long,
@field:Schema(description = "결제 위젯을 통해 받은 결제 키") @field:Schema(description = "결제 위젯을 통해 받은 결제 키")
@ -39,23 +27,14 @@ data class ReservationRequest(
@field:Schema(description = "결제 타입", example = "NORMAL") @field:Schema(description = "결제 타입", example = "NORMAL")
val paymentType: String val paymentType: String
) { )
@get:JsonIgnore
val paymentRequest: PaymentApproveRequest
get() = PaymentApproveRequest(paymentKey, orderId, amount, paymentType)
}
@Schema(name = "예약 대기 저장 요청", description = "회원의 예약 대기 요청시 사용됩니다.") fun ReservationCreateWithPaymentRequest.toPaymentApproveRequest(): PaymentApproveRequest = PaymentApproveRequest(
data class WaitingRequest( paymentKey, orderId, amount, paymentType
)
@field:Schema(description = "예약 날짜. 지난 날짜는 지정할 수 없으며, yyyy-MM-dd 형식으로 입력해야 합니다.", type = "string", example = "2022-12-31") data class WaitingCreateRequest(
val date: LocalDate, val date: LocalDate,
@field:Schema(description = "예약 시간 ID", example = "1")
val timeId: Long, val timeId: Long,
@field:Schema(description = "테마 ID", example = "1")
val themeId: Long val themeId: Long
) )

View File

@ -11,65 +11,42 @@ import roomescape.theme.web.toResponse
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime
@Schema(name = "회원의 예약 및 대기 응답", description = "회원의 예약 및 대기 정보 응답시 사용됩니다.") data class MyReservationRetrieveResponse(
data class MyReservationResponse(
@field:Schema(description = "예약 번호. 예약을 식별할 때 사용합니다.")
val id: Long, val id: Long,
@field:Schema(description = "테마 이름")
val themeName: String, val themeName: String,
@field:Schema(description = "예약 날짜", type = "string", example = "2022-12-31")
val date: LocalDate, val date: LocalDate,
@field:Schema(description = "예약 시간", type = "string", example = "09:00")
val time: LocalTime, val time: LocalTime,
@field:Schema(description = "예약 상태", type = "string")
val status: ReservationStatus, val status: ReservationStatus,
@field:Schema(description = "대기 순번. 확정된 예약은 0의 값을 가집니다.")
@field:Schema(description = "예약 대기 상태일 때의 대기 순번. 확정된 예약은 0의 값을 가집니다.")
val rank: Long, val rank: Long,
@field:Schema(description = "결제 키. 결제가 완료된 예약에만 값이 존재합니다.") @field:Schema(description = "결제 키. 결제가 완료된 예약에만 값이 존재합니다.")
val paymentKey: String?, val paymentKey: String?,
@field:Schema(description = "결제 금액. 결제가 완료된 예약에만 값이 존재합니다.") @field:Schema(description = "결제 금액. 결제가 완료된 예약에만 값이 존재합니다.")
val amount: Long? val amount: Long?
) )
@Schema(name = "회원의 예약 및 대기 목록 조회 응답", description = "회원의 예약 및 대기 목록 조회 응답시 사용됩니다.") data class MyReservationRetrieveListResponse(
data class MyReservationsResponse(
@field:Schema(description = "현재 로그인한 회원의 예약 및 대기 목록") @field:Schema(description = "현재 로그인한 회원의 예약 및 대기 목록")
val reservations: List<MyReservationResponse> val reservations: List<MyReservationRetrieveResponse>
) )
@Schema(name = "예약 정보", description = "예약 저장 및 조회 응답에 사용됩니다.") data class ReservationRetrieveResponse(
data class ReservationResponse(
@field:Schema(description = "예약 번호. 예약을 식별할 때 사용합니다.")
val id: Long, val id: Long,
@field:Schema(description = "예약 날짜", type = "string", example = "2022-12-31")
val date: LocalDate, val date: LocalDate,
@field:Schema(description = "예약한 회원 정보")
@field:JsonProperty("member") @field:JsonProperty("member")
val member: MemberRetrieveResponse, val member: MemberRetrieveResponse,
@field:Schema(description = "예약 시간 정보")
@field:JsonProperty("time") @field:JsonProperty("time")
val time: TimeCreateResponse, val time: TimeCreateResponse,
@field:Schema(description = "예약한 테마 정보")
@field:JsonProperty("theme") @field:JsonProperty("theme")
val theme: ThemeResponse, val theme: ThemeResponse,
@field:Schema(description = "예약 상태", type = "string")
val status: ReservationStatus val status: ReservationStatus
) )
fun ReservationEntity.toCreateResponse(): ReservationResponse = ReservationResponse( fun ReservationEntity.toRetrieveResponse(): ReservationRetrieveResponse = ReservationRetrieveResponse(
id = this.id!!, id = this.id!!,
date = this.date, date = this.date,
member = this.member.toRetrieveResponse(), member = this.member.toRetrieveResponse(),
@ -78,8 +55,6 @@ fun ReservationEntity.toCreateResponse(): ReservationResponse = ReservationRespo
status = this.reservationStatus status = this.reservationStatus
) )
@Schema(name = "예약 목록 조회 응답", description = "모든 예약 정보 조회 응답시 사용됩니다.") data class ReservationRetrieveListResponse(
data class ReservationsResponse( val reservations: List<ReservationRetrieveResponse>
@field:Schema(description = "모든 예약 및 대기 목록")
val reservations: List<ReservationResponse>
) )

View File

@ -52,7 +52,7 @@ class TossPaymentClientTest(
assertSoftly(paymentResponse) { assertSoftly(paymentResponse) {
this.paymentKey shouldBe paymentRequest.paymentKey this.paymentKey shouldBe paymentRequest.paymentKey
this.orderId shouldBe paymentRequest.orderId this.orderId shouldBe paymentRequest.orderId
this.amount shouldBe paymentRequest.amount this.totalAmount shouldBe paymentRequest.amount
} }
} }

View File

@ -13,8 +13,8 @@ import roomescape.payment.web.PaymentCancelRequest
import roomescape.payment.web.toCreateResponse import roomescape.payment.web.toCreateResponse
import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationStatus import roomescape.reservation.infrastructure.persistence.ReservationStatus
import roomescape.reservation.web.ReservationRequest import roomescape.reservation.web.ReservationCreateWithPaymentRequest
import roomescape.reservation.web.ReservationResponse import roomescape.reservation.web.ReservationRetrieveResponse
import roomescape.util.* import roomescape.util.*
class ReservationWithPaymentServiceTest : FunSpec({ class ReservationWithPaymentServiceTest : FunSpec({
@ -26,37 +26,37 @@ class ReservationWithPaymentServiceTest : FunSpec({
paymentService = paymentService paymentService = paymentService
) )
val reservationRequest: ReservationRequest = ReservationFixture.createRequest() val reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest = ReservationFixture.createRequest()
val paymentApproveResponse = PaymentFixture.createApproveResponse() val paymentApproveResponse = PaymentFixture.createApproveResponse()
val memberId = 1L val memberId = 1L
val reservationEntity: ReservationEntity = ReservationFixture.create( val reservationEntity: ReservationEntity = ReservationFixture.create(
id = 1L, id = 1L,
date = reservationRequest.date, date = reservationCreateWithPaymentRequest.date,
time = TimeFixture.create(id = reservationRequest.timeId), time = TimeFixture.create(id = reservationCreateWithPaymentRequest.timeId),
theme = ThemeFixture.create(id = reservationRequest.themeId), theme = ThemeFixture.create(id = reservationCreateWithPaymentRequest.themeId),
member = MemberFixture.create(id = memberId), member = MemberFixture.create(id = memberId),
status = ReservationStatus.CONFIRMED status = ReservationStatus.CONFIRMED
) )
val paymentEntity: PaymentEntity = PaymentFixture.create( val paymentEntity: PaymentEntity = PaymentFixture.create(
id = 1L, id = 1L,
orderId = reservationRequest.orderId, orderId = reservationCreateWithPaymentRequest.orderId,
paymentKey = reservationRequest.paymentKey, paymentKey = reservationCreateWithPaymentRequest.paymentKey,
totalAmount = reservationRequest.amount, totalAmount = reservationCreateWithPaymentRequest.amount,
reservation = reservationEntity, reservation = reservationEntity,
) )
context("addReservationWithPayment") { context("addReservationWithPayment") {
test("예약 및 결제 정보를 저장한다.") { test("예약 및 결제 정보를 저장한다.") {
every { every {
reservationService.addReservation(reservationRequest, memberId) reservationService.addReservation(reservationCreateWithPaymentRequest, memberId)
} returns reservationEntity } returns reservationEntity
every { every {
paymentService.createPayment(paymentApproveResponse, reservationEntity) paymentService.createPayment(paymentApproveResponse, reservationEntity)
} returns paymentEntity.toCreateResponse() } returns paymentEntity.toCreateResponse()
val result: ReservationResponse = reservationWithPaymentService.addReservationWithPayment( val result: ReservationRetrieveResponse = reservationWithPaymentService.addReservationWithPayment(
request = reservationRequest, request = reservationCreateWithPaymentRequest,
paymentInfo = paymentApproveResponse, paymentInfo = paymentApproveResponse,
memberId = memberId memberId = memberId
) )

View File

@ -8,7 +8,7 @@ import jakarta.persistence.EntityManager
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.data.repository.findByIdOrNull import org.springframework.data.repository.findByIdOrNull
import roomescape.payment.infrastructure.persistence.PaymentEntity import roomescape.payment.infrastructure.persistence.PaymentEntity
import roomescape.reservation.web.MyReservationResponse import roomescape.reservation.web.MyReservationRetrieveResponse
import roomescape.theme.infrastructure.persistence.ThemeEntity import roomescape.theme.infrastructure.persistence.ThemeEntity
import roomescape.util.PaymentFixture import roomescape.util.PaymentFixture
import roomescape.util.ReservationFixture import roomescape.util.ReservationFixture
@ -168,7 +168,7 @@ class ReservationRepositoryTest(
entityManager.clear() entityManager.clear()
} }
val result: List<MyReservationResponse> = reservationRepository.findMyReservations(reservation.member.id!!) val result: List<MyReservationRetrieveResponse> = reservationRepository.findMyReservations(reservation.member.id!!)
result shouldHaveSize 1 result shouldHaveSize 1
assertSoftly(result.first()) { assertSoftly(result.first()) {
@ -179,7 +179,7 @@ class ReservationRepositoryTest(
} }
test("결제 정보가 없다면 paymentKey와 amount는 null로 반환한다.") { test("결제 정보가 없다면 paymentKey와 amount는 null로 반환한다.") {
val result: List<MyReservationResponse> = reservationRepository.findMyReservations(reservation.member.id!!) val result: List<MyReservationRetrieveResponse> = reservationRepository.findMyReservations(reservation.member.id!!)
result shouldHaveSize 1 result shouldHaveSize 1
assertSoftly(result.first()) { assertSoftly(result.first()) {

View File

@ -66,7 +66,7 @@ class ReservationControllerTest(
val paymentApproveResponse = PaymentFixture.createApproveResponse().copy( val paymentApproveResponse = PaymentFixture.createApproveResponse().copy(
paymentKey = reservationRequest.paymentKey, paymentKey = reservationRequest.paymentKey,
orderId = reservationRequest.orderId, orderId = reservationRequest.orderId,
amount = reservationRequest.amount, totalAmount = reservationRequest.amount,
) )
every { every {
@ -116,7 +116,7 @@ class ReservationControllerTest(
val paymentApproveResponse = PaymentFixture.createApproveResponse().copy( val paymentApproveResponse = PaymentFixture.createApproveResponse().copy(
paymentKey = reservationRequest.paymentKey, paymentKey = reservationRequest.paymentKey,
orderId = reservationRequest.orderId, orderId = reservationRequest.orderId,
amount = reservationRequest.amount, totalAmount = reservationRequest.amount,
) )
every { every {
@ -409,8 +409,8 @@ class ReservationControllerTest(
context("POST /reservations/admin") { context("POST /reservations/admin") {
test("관리자가 예약을 추가하면 결제 대기 상태로 예약 생성") { test("관리자가 예약을 추가하면 결제 대기 상태로 예약 생성") {
val member = login(MemberFixture.create(role = Role.ADMIN)) val member = login(MemberFixture.create(role = Role.ADMIN))
val adminRequest: AdminReservationRequest = createRequest().let { val adminRequest: AdminReservationCreateRequest = createRequest().let {
AdminReservationRequest( AdminReservationCreateRequest(
date = it.date, date = it.date,
themeId = it.themeId, themeId = it.themeId,
timeId = it.timeId, timeId = it.timeId,
@ -473,8 +473,8 @@ class ReservationControllerTest(
context("POST /reservations/waiting") { context("POST /reservations/waiting") {
test("회원이 대기 예약을 추가한다.") { test("회원이 대기 예약을 추가한다.") {
val member = login(MemberFixture.create(role = Role.MEMBER)) val member = login(MemberFixture.create(role = Role.MEMBER))
val waitingRequest: WaitingRequest = createRequest().let { val waitingCreateRequest: WaitingCreateRequest = createRequest().let {
WaitingRequest( WaitingCreateRequest(
date = it.date, date = it.date,
themeId = it.themeId, themeId = it.themeId,
timeId = it.timeId timeId = it.timeId
@ -484,7 +484,7 @@ class ReservationControllerTest(
Given { Given {
port(port) port(port)
contentType(MediaType.APPLICATION_JSON_VALUE) contentType(MediaType.APPLICATION_JSON_VALUE)
body(waitingRequest) body(waitingCreateRequest)
}.When { }.When {
post("/reservations/waiting") post("/reservations/waiting")
}.Then { }.Then {
@ -513,7 +513,7 @@ class ReservationControllerTest(
} }
// 이미 예약된 시간, 테마로 대기 예약 요청 // 이미 예약된 시간, 테마로 대기 예약 요청
val waitingRequest = WaitingRequest( val waitingCreateRequest = WaitingCreateRequest(
date = reservationRequest.date, date = reservationRequest.date,
themeId = reservationRequest.themeId, themeId = reservationRequest.themeId,
timeId = reservationRequest.timeId timeId = reservationRequest.timeId
@ -522,7 +522,7 @@ class ReservationControllerTest(
Given { Given {
port(port) port(port)
contentType(MediaType.APPLICATION_JSON_VALUE) contentType(MediaType.APPLICATION_JSON_VALUE)
body(waitingRequest) body(waitingCreateRequest)
}.When { }.When {
post("/reservations/waiting") post("/reservations/waiting")
}.Then { }.Then {
@ -734,14 +734,14 @@ class ReservationControllerTest(
fun createRequest( fun createRequest(
theme: ThemeEntity = ThemeFixture.create(), theme: ThemeEntity = ThemeFixture.create(),
time: TimeEntity = TimeFixture.create(), time: TimeEntity = TimeFixture.create(),
): ReservationRequest { ): ReservationCreateWithPaymentRequest {
lateinit var reservationRequest: ReservationRequest lateinit var reservationCreateWithPaymentRequest: ReservationCreateWithPaymentRequest
transactionTemplate.executeWithoutResult { transactionTemplate.executeWithoutResult {
entityManager.persist(theme) entityManager.persist(theme)
entityManager.persist(time) entityManager.persist(time)
reservationRequest = ReservationFixture.createRequest( reservationCreateWithPaymentRequest = ReservationFixture.createRequest(
themeId = theme.id!!, themeId = theme.id!!,
timeId = time.id!!, timeId = time.id!!,
) )
@ -750,7 +750,7 @@ class ReservationControllerTest(
entityManager.clear() entityManager.clear()
} }
return reservationRequest return reservationCreateWithPaymentRequest
} }
fun login(member: MemberEntity): MemberEntity { fun login(member: MemberEntity): MemberEntity {

View File

@ -13,8 +13,8 @@ import roomescape.payment.web.PaymentCancelResponse
import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationStatus import roomescape.reservation.infrastructure.persistence.ReservationStatus
import roomescape.reservation.infrastructure.persistence.TimeEntity import roomescape.reservation.infrastructure.persistence.TimeEntity
import roomescape.reservation.web.ReservationRequest import roomescape.reservation.web.ReservationCreateWithPaymentRequest
import roomescape.reservation.web.WaitingRequest import roomescape.reservation.web.WaitingCreateRequest
import roomescape.theme.infrastructure.persistence.ThemeEntity import roomescape.theme.infrastructure.persistence.ThemeEntity
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime
@ -88,7 +88,7 @@ object ReservationFixture {
orderId: String = "orderId", orderId: String = "orderId",
amount: Long = 10000L, amount: Long = 10000L,
paymentType: String = "NORMAL", paymentType: String = "NORMAL",
): ReservationRequest = ReservationRequest( ): ReservationCreateWithPaymentRequest = ReservationCreateWithPaymentRequest(
date = date, date = date,
timeId = timeId, timeId = timeId,
themeId = themeId, themeId = themeId,
@ -102,7 +102,7 @@ object ReservationFixture {
date: LocalDate = LocalDate.now().plusWeeks(1), date: LocalDate = LocalDate.now().plusWeeks(1),
themeId: Long = 1L, themeId: Long = 1L,
timeId: Long = 1L timeId: Long = 1L
): WaitingRequest = WaitingRequest( ): WaitingCreateRequest = WaitingCreateRequest(
date = date, date = date,
timeId = timeId, timeId = timeId,
themeId = themeId themeId = themeId
@ -168,7 +168,7 @@ object PaymentFixture {
paymentKey = PAYMENT_KEY, paymentKey = PAYMENT_KEY,
orderId = ORDER_ID, orderId = ORDER_ID,
approvedAt = OffsetDateTime.now(), approvedAt = OffsetDateTime.now(),
amount = AMOUNT totalAmount = AMOUNT
) )
fun createCancelRequest(): PaymentCancelRequest = PaymentCancelRequest( fun createCancelRequest(): PaymentCancelRequest = PaymentCancelRequest(