265 lines
9.9 KiB
Kotlin

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)
}
}
}