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