215 lines
8.2 KiB
Kotlin

package roomescape.supports
import org.springframework.data.repository.findByIdOrNull
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.toDetailResponse
import roomescape.payment.web.toPaymentDetailResponse
import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationRepository
import roomescape.reservation.infrastructure.persistence.ReservationStatus
import roomescape.reservation.web.PendingReservationCreateRequest
import roomescape.reservation.web.toEntity
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.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 roomescape.theme.web.toEntity
import roomescape.user.infrastructure.persistence.UserEntity
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 createStore(
id: Long = tsidFactory.next(),
name: String = "행복${randomPhoneNumber()}호점",
address: String = "강북구 행복로 $name",
contact: String = randomPhoneNumber(),
businessRegNum: String = randomBusinessRegNum(),
regionCode: String = "1111000000",
status: StoreStatus = StoreStatus.ACTIVE,
createdBy: Long = 0L,
): StoreEntity {
return StoreEntity(
id = id,
name = name,
address = address,
contact = contact,
businessRegNum = businessRegNum,
regionCode = regionCode,
status = status
).apply {
this.createdBy = createdBy
this.updatedBy = createdBy
}.also {
storeRepository.save(it)
}
}
fun createTheme(
request: ThemeCreateRequest = ThemeFixture.createRequest
): ThemeEntity {
return request.toEntity(tsidFactory.next()).also { themeRepository.save(it) }
}
fun createSchedule(
storeId: Long = tsidFactory.next(),
request: ScheduleCreateRequest = ScheduleFixture.createRequest,
status: ScheduleStatus = ScheduleStatus.AVAILABLE
): ScheduleEntity {
val themeId: Long = if (themeRepository.existsById(request.themeId)) {
request.themeId
} else {
createTheme().id
}
val storeId: Long = if (storeRepository.existsById(storeId)) {
storeId
} else {
createStore(id = storeId).id
}
val schedule: ScheduleEntity = ScheduleFixture.create(
date = request.date, time = request.time, storeId = storeId, themeId = themeId,
).apply {
this.status = status
}
return scheduleRepository.save(schedule)
}
fun createPendingReservation(
user: UserEntity,
storeId: Long = tsidFactory.next(),
themeRequest: ThemeCreateRequest = ThemeFixture.createRequest,
scheduleRequest: ScheduleCreateRequest = ScheduleFixture.createRequest,
reservationRequest: PendingReservationCreateRequest = ReservationFixture.pendingCreateRequest,
): ReservationEntity {
val themeId: Long = if (themeRepository.existsById(scheduleRequest.themeId)) {
scheduleRequest.themeId
} else {
createTheme(themeRequest).id
}
val scheduleId: Long = if (scheduleRepository.existsById(reservationRequest.scheduleId)) {
reservationRequest.scheduleId
} else {
createSchedule(
storeId = storeId,
request = scheduleRequest.copy(themeId = themeId),
status = ScheduleStatus.HOLD
).id
}
val reservation = ReservationFixture.pendingCreateRequest.copy(
scheduleId = scheduleId,
reserverName = reservationRequest.reserverName,
reserverContact = reservationRequest.reserverContact,
participantCount = reservationRequest.participantCount,
requirement = reservationRequest.requirement,
).toEntity(id = tsidFactory.next(), userId = user.id)
return reservationRepository.save(reservation)
}
fun createConfirmReservation(
user: UserEntity,
storeId: Long = tsidFactory.next(),
themeRequest: ThemeCreateRequest = ThemeFixture.createRequest,
scheduleRequest: ScheduleCreateRequest = ScheduleFixture.createRequest,
reservationRequest: PendingReservationCreateRequest = ReservationFixture.pendingCreateRequest,
): ReservationEntity {
return createPendingReservation(user, storeId, themeRequest, scheduleRequest, reservationRequest).apply {
this.status = ReservationStatus.CONFIRMED
}.also {
reservationRepository.save(it)
scheduleRepository.findByIdOrNull(it.scheduleId)?.let { schedule ->
schedule.status = ScheduleStatus.RESERVED
scheduleRepository.save(schedule)
}
}
}
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
)
}
}