package roomescape.supports import io.restassured.module.kotlin.extensions.Extract import io.restassured.module.kotlin.extensions.Given import io.restassured.module.kotlin.extensions.When import org.springframework.data.repository.findByIdOrNull import org.springframework.http.MediaType import roomescape.common.config.next import roomescape.payment.business.PaymentWriter import roomescape.payment.infrastructure.client.CardDetail import roomescape.payment.infrastructure.client.EasyPayDetail import roomescape.payment.infrastructure.client.TransferDetail import roomescape.payment.infrastructure.common.PaymentMethod import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity import roomescape.payment.infrastructure.persistence.PaymentEntity import roomescape.payment.infrastructure.persistence.PaymentRepository import roomescape.payment.web.PaymentConfirmRequest import roomescape.payment.web.PaymentWithDetailResponse import roomescape.payment.web.toPaymentDetailResponse import roomescape.payment.web.toDetailResponse import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationRepository import roomescape.reservation.web.PendingReservationCreateRequest import roomescape.schedule.infrastructure.persistence.ScheduleEntity import roomescape.schedule.infrastructure.persistence.ScheduleRepository import roomescape.schedule.infrastructure.persistence.ScheduleStatus import roomescape.schedule.web.ScheduleCreateRequest import roomescape.schedule.web.ScheduleUpdateRequest import roomescape.store.infrastructure.persistence.StoreEntity import roomescape.store.infrastructure.persistence.StoreRepository import roomescape.store.infrastructure.persistence.StoreStatus import roomescape.theme.infrastructure.persistence.ThemeEntity import roomescape.theme.infrastructure.persistence.ThemeRepository import roomescape.theme.web.ThemeCreateRequest import java.time.LocalDateTime class DummyInitializer( private val storeRepository: StoreRepository, private val themeRepository: ThemeRepository, private val scheduleRepository: ScheduleRepository, private val reservationRepository: ReservationRepository, private val paymentRepository: PaymentRepository, private val paymentWriter: PaymentWriter ) { fun createTheme(adminToken: String, request: ThemeCreateRequest): ThemeEntity { val createdThemeId: Long = Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $adminToken") body(request) } When { post("/admin/themes") } Extract { path("data.id") } return themeRepository.findByIdOrNull(createdThemeId) ?: throw RuntimeException("unexpected error occurred") } fun createSchedule( adminToken: String, request: ScheduleCreateRequest, status: ScheduleStatus = ScheduleStatus.AVAILABLE ): ScheduleEntity { val themeId: Long = if (themeRepository.existsById(request.themeId)) { request.themeId } else { createTheme( adminToken = adminToken, request = ThemeFixture.createRequest.copy(name = "theme-${System.currentTimeMillis()}") ).id } val createdScheduleId: Long = Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $adminToken") body(request.copy(themeId = themeId)) } When { post("/schedules") } Extract { path("data.id") } Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $adminToken") body(ScheduleUpdateRequest(status = status)) } When { patch("/schedules/$createdScheduleId") } return scheduleRepository.findByIdOrNull(createdScheduleId) ?: throw RuntimeException("unexpected error occurred") } fun createPendingReservation( adminToken: String, reserverToken: String, themeRequest: ThemeCreateRequest = ThemeFixture.createRequest, scheduleRequest: ScheduleCreateRequest = ScheduleFixture.createRequest, reservationRequest: PendingReservationCreateRequest = ReservationFixture.pendingCreateRequest, ): ReservationEntity { val themeId: Long = if (themeRepository.existsById(scheduleRequest.themeId)) { scheduleRequest.themeId } else if (themeRepository.existsById(reservationRequest.scheduleId)) { reservationRequest.scheduleId } else { createTheme( adminToken = adminToken, request = themeRequest ).id } val scheduleId: Long = if (scheduleRepository.existsById(reservationRequest.scheduleId)) { reservationRequest.scheduleId } else { createSchedule( adminToken = adminToken, request = scheduleRequest.copy(themeId = themeId), status = ScheduleStatus.HOLD ).id } return createPendingReservation( reserverToken = reserverToken, request = reservationRequest.copy(scheduleId = scheduleId) ) } fun createConfirmReservation( adminToken: String, reserverToken: String, themeRequest: ThemeCreateRequest = ThemeFixture.createRequest, scheduleRequest: ScheduleCreateRequest = ScheduleFixture.createRequest, reservationRequest: PendingReservationCreateRequest = ReservationFixture.pendingCreateRequest, ): ReservationEntity { val themeId: Long = if (themeRepository.existsById(scheduleRequest.themeId)) { scheduleRequest.themeId } else if (themeRepository.existsById(reservationRequest.scheduleId)) { reservationRequest.scheduleId } else { createTheme( adminToken = adminToken, request = themeRequest ).id } val scheduleId: Long = if (scheduleRepository.existsById(reservationRequest.scheduleId)) { reservationRequest.scheduleId } else { createSchedule( adminToken = adminToken, request = scheduleRequest.copy(themeId = themeId), status = ScheduleStatus.HOLD ).id } val reservation = createPendingReservation( reserverToken = reserverToken, request = reservationRequest.copy(scheduleId = scheduleId) ) Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $reserverToken") } When { post("/reservations/${reservation.id}/confirm") } return reservationRepository.findByIdOrNull(reservation.id) ?: throw RuntimeException("unexpected error occurred") } fun createPayment( reservationId: Long, request: PaymentConfirmRequest = PaymentFixture.confirmRequest, cardDetail: CardDetail? = null, easyPayDetail: EasyPayDetail? = null, transferDetail: TransferDetail? = null, ): PaymentWithDetailResponse { val method = if (easyPayDetail != null) { PaymentMethod.EASY_PAY } else if (cardDetail != null) { PaymentMethod.CARD } else if (transferDetail != null) { PaymentMethod.TRANSFER } else { throw AssertionError("결제타입 확인 필요.") } val clientConfirmResponse = PaymentFixture.confirmResponse( paymentKey = request.paymentKey, amount = request.amount, method = method, cardDetail = cardDetail, easyPayDetail = easyPayDetail, transferDetail = transferDetail ) val payment = paymentWriter.createPayment( reservationId = reservationId, orderId = request.orderId, paymentType = request.paymentType, paymentClientConfirmResponse = clientConfirmResponse ) val detail = paymentWriter.createDetail(clientConfirmResponse, payment.id) return payment.toDetailResponse(detail = detail.toPaymentDetailResponse(), cancel = null) } fun cancelPayment( userId: Long, reservationId: Long, cancelReason: String, ): CanceledPaymentEntity { val payment: PaymentEntity = paymentRepository.findByReservationId(reservationId) ?: throw AssertionError("Unexpected Exception Occurred.") val clientCancelResponse = PaymentFixture.cancelResponse( amount = payment.totalAmount, cancelReason = cancelReason, ) return paymentWriter.cancel( userId, payment, requestedAt = LocalDateTime.now(), clientCancelResponse ) } private fun createPendingReservation( reserverToken: String, request: PendingReservationCreateRequest, ): ReservationEntity { val createdReservationId: Long = Given { contentType(MediaType.APPLICATION_JSON_VALUE) header("Authorization", "Bearer $reserverToken") body(request.copy(scheduleId = request.scheduleId)) } When { post("/reservations/pending") } Extract { path("data.id") } return reservationRepository.findByIdOrNull(createdReservationId) ?: throw RuntimeException("unexpected error occurred") } fun createStore(): StoreEntity { return StoreEntity( id = tsidFactory.next(), name = "Hello 매장-${System.currentTimeMillis()}", address = "강북구 행복로 123", contact = randomPhoneNumber(), businessRegNum = randomBusinessRegNum(), regionCode = "1111000000", status = StoreStatus.ACTIVE ).also { storeRepository.save(it) } } }