Skip to content

Commit

Permalink
Merge pull request #263 from Nexters/feature/256
Browse files Browse the repository at this point in the history
feat/256 : 결제 내역에 선물 케이스 추가
  • Loading branch information
HamBP authored Jul 27, 2024
2 parents 98fc7a0 + 8781c6a commit 2fd431c
Show file tree
Hide file tree
Showing 31 changed files with 462 additions and 103 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.nexters.boolti.data.datasource

import com.nexters.boolti.data.network.api.GiftService
import com.nexters.boolti.data.network.request.GiftCancelRequest
import com.nexters.boolti.data.network.request.GiftReceiveRequest
import com.nexters.boolti.data.network.response.ApproveGiftPaymentResponse
import com.nexters.boolti.data.network.response.GiftPaymentInfoResponse
import com.nexters.boolti.data.network.response.GiftResponse
import com.nexters.boolti.data.network.response.ImageResponse
import com.nexters.boolti.domain.request.FreeGiftRequest
Expand All @@ -23,4 +25,10 @@ internal class GiftDataSource @Inject constructor(
suspend fun getGift(giftUuid: String): GiftResponse = service.getGift(giftUuid)

suspend fun getGiftImages(): List<ImageResponse> = service.getGiftImages()

suspend fun getGiftPaymentInfo(giftId: String): GiftPaymentInfoResponse =
service.getGiftPaymentInfo(giftId)

suspend fun cancelGift(giftUuid: String): Boolean =
service.cancelGift(GiftCancelRequest(giftUuid = giftUuid))
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.nexters.boolti.data.network.api

import com.nexters.boolti.data.network.request.GiftCancelRequest
import com.nexters.boolti.data.network.request.GiftReceiveRequest
import com.nexters.boolti.data.network.response.ApproveGiftPaymentResponse
import com.nexters.boolti.data.network.response.GiftPaymentInfoResponse
import com.nexters.boolti.data.network.response.GiftResponse
import com.nexters.boolti.data.network.response.ImageResponse
import com.nexters.boolti.domain.request.FreeGiftRequest
Expand All @@ -26,4 +28,10 @@ internal interface GiftService {

@GET("/app/api/v1/gift/img-list")
suspend fun getGiftImages(): List<ImageResponse>

@GET("app/api/v1/gift/approve-payment-info/{giftId}")
suspend fun getGiftPaymentInfo(@Path("giftId") giftId: String): GiftPaymentInfoResponse

@POST("app/api/v1/order/cancel-gift")
suspend fun cancelGift(@Body request: GiftCancelRequest): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.nexters.boolti.data.network.request

import kotlinx.serialization.Serializable

@Serializable
data class GiftCancelRequest(
val giftUuid: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.nexters.boolti.data.network.response

import com.nexters.boolti.data.network.response.ReservationDetailResponse.CardDetailResponse
import com.nexters.boolti.data.network.response.ReservationDetailResponse.EasyPayDetailResponse
import com.nexters.boolti.data.util.toLocalDateTime
import com.nexters.boolti.data.util.toPaymentType
import com.nexters.boolti.data.util.toReservationState
import com.nexters.boolti.domain.model.ReservationDetail
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
internal data class GiftPaymentInfoResponse(
val csReservationId: String,
val showImg: String,
val showName: String,
val showDate: String,
val salesTicketName: String,
val salesTicketType: String,
val ticketCount: Int,
val salesEndTime: String,
val meansType: String?,
val totalAmountPrice: Int = 0,
val reservationStatus: String,
val senderName: String,
val senderPhoneNumber: String,
val recipientName: String = "",
val recipientPhoneNumber: String = "",
val giftId: String,
val giftUuid: String,
val giftMessage: String,
val giftInvitePath: String,
val cardDetail: CardDetailResponse? = null,
val easyPayDetail: EasyPayDetailResponse? = null,
) {
fun toDomain(): ReservationDetail {
return ReservationDetail(
id = giftId,
giftUuid = giftUuid,
giftInviteImage = giftInvitePath,
showImage = showImg,
showName = showName,
showDate = showDate.toLocalDateTime(),
ticketName = salesTicketName,
isInviteTicket = false,
ticketCount = ticketCount,
bankName = "",
accountNumber = "",
accountHolder = "",
salesEndDateTime = salesEndTime.toLocalDateTime(),
paymentType = meansType.toPaymentType(),
totalAmountPrice = totalAmountPrice,
reservationState = reservationStatus.toReservationState(),
completedDateTime = null,
visitorName = recipientName,
visitorPhoneNumber = recipientPhoneNumber,
depositorName = senderName,
depositorPhoneNumber = senderPhoneNumber,
csReservationId = csReservationId,
cardDetail = cardDetail?.toDomain(),
provider = easyPayDetail?.provider ?: ""
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ internal data class ReservationDetailResponse(
totalAmountPrice = totalAmountPrice,
reservationState = reservationStatus.toReservationState(),
completedDateTime = completedTimeStamp?.toLocalDateTime(),
ticketHolderName = reservationName,
ticketHolderPhoneNumber = reservationPhoneNumber,
visitorName = reservationName,
visitorPhoneNumber = reservationPhoneNumber,
depositorName = depositorName,
depositorPhoneNumber = depositorPhoneNumber,
csReservationId = csReservationId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@ internal data class ReservationResponse(
val reservationId: String,
val reservationStatus: String,
val reservationDate: String,
val giftId: String?,
val showName: String,
val showImg: String,
val salesTicketName: String,
val ticketCount: Int,
val ticketPrice: Int = 0,
val recipientName: String?,
) {
fun toDomain(): Reservation {
return Reservation(
id = reservationId,
giftId = giftId,
reservationState = reservationStatus.toReservationState(),
reservationDateTime = reservationDate.toLocalDateTime(),
showName = showName,
showImage = showImg,
salesTicketName = salesTicketName,
ticketCount = ticketCount,
ticketPrice = ticketPrice,
receiver = recipientName,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.nexters.boolti.data.network.response.toDomains
import com.nexters.boolti.domain.model.ApproveGiftPayment
import com.nexters.boolti.domain.model.Gift
import com.nexters.boolti.domain.model.ImagePair
import com.nexters.boolti.domain.model.ReservationDetail
import com.nexters.boolti.domain.repository.GiftRepository
import com.nexters.boolti.domain.request.FreeGiftRequest
import com.nexters.boolti.domain.request.GiftApproveRequest
Expand Down Expand Up @@ -35,4 +36,12 @@ internal class GiftRepositoryImpl @Inject constructor(
override fun getGiftImages(): Flow<List<ImagePair>> = flow {
emit(dataSource.getGiftImages().toDomains())
}

override fun getGiftPaymentInfo(giftId: String): Flow<ReservationDetail> = flow {
emit(dataSource.getGiftPaymentInfo(giftId).toDomain())
}

override fun cancelGift(giftUuid: String): Flow<Boolean> = flow {
emit(dataSource.cancelGift(giftUuid))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal fun String.toReservationState(): ReservationState {
"RESERVATION_COMPLETED" -> ReservationState.RESERVED
"WAITING_FOR_REFUND" -> ReservationState.REFUNDING
"REFUND_COMPLETED" -> ReservationState.REFUNDED
"WAITING_FOR_GIFT_RECEIPT" -> ReservationState.REGISTERING_GIFT
// TODO: 선물 등록 완료 상태 추가
else -> ReservationState.UNDEFINED
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import java.time.LocalDateTime

data class Reservation(
val id: String,
val giftId: String?,
val reservationState: ReservationState,
val reservationDateTime: LocalDateTime,
val showName: String,
val showImage: String,
val salesTicketName: String,
val ticketCount: Int,
val ticketPrice: Int,
)
val receiver: String?,
) {
val isGift = giftId != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ data class ReservationDetail(
val showImage: String,
val showName: String,
val showDate: LocalDateTime,
val giftUuid: String? = null,
val giftInviteImage: String = "",
val ticketName: String,
val isInviteTicket: Boolean,
val ticketCount: Int,
Expand All @@ -18,14 +20,28 @@ data class ReservationDetail(
val totalAmountPrice: Int,
val reservationState: ReservationState,
val completedDateTime: LocalDateTime?,
val ticketHolderName: String,
val ticketHolderPhoneNumber: String,
val visitorName: String,
val visitorPhoneNumber: String,
val depositorName: String,
val depositorPhoneNumber: String,
val csReservationId: String,
val cardDetail: CardDetail?,
val provider: String = "",
) {
val isGift = giftUuid != null

val isRefundable: Boolean
get() {
return if (isGift) {
reservationState == ReservationState.REGISTERING_GIFT &&
salesEndDateTime >= LocalDateTime.now()
} else {
reservationState == ReservationState.RESERVED &&
!isInviteTicket &&
salesEndDateTime >= LocalDateTime.now()
}
}

/**
* @param installmentPlanMonths 할부 개월 수. 0 이면 일시불
* @param issuerCode 카드 발급사 [숫자 코드](https://docs.tosspayments.com/reference/codes#%EC%B9%B4%EB%93%9C%EC%82%AC-%EC%BD%94%EB%93%9C)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ enum class ReservationState {
RESERVED,
REFUNDING,
REFUNDED,
REGISTERING_GIFT,
UNDEFINED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import com.nexters.boolti.domain.model.ApproveGiftPayment
import com.nexters.boolti.domain.model.Gift
import com.nexters.boolti.domain.model.ImagePair
import com.nexters.boolti.domain.request.FreeGiftRequest
import com.nexters.boolti.domain.model.ReservationDetail
import com.nexters.boolti.domain.request.GiftApproveRequest
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

interface GiftRepository {
fun receiveGift(giftUuid: String): Flow<Boolean>
Expand All @@ -18,4 +18,8 @@ interface GiftRepository {
fun getGift(giftUuid: String): Flow<Gift>

fun getGiftImages(): Flow<List<ImagePair>>

fun getGiftPaymentInfo(giftId: String): Flow<ReservationDetail>

fun cancelGift(giftUuid: String): Flow<Boolean>
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ import com.nexters.boolti.presentation.theme.Error
import com.nexters.boolti.presentation.theme.Grey30
import com.nexters.boolti.presentation.theme.Success

fun ReservationState.toDescriptionAndColorPair(): Pair<Int, Color> {
fun ReservationState.toDescriptionAndColorPair(isGift: Boolean): Pair<Int, Color> {
return when (this) {
ReservationState.DEPOSITING -> Pair(R.string.reservations_depositing, Grey30)
ReservationState.REFUNDING -> Pair(R.string.reservations_refunding, Grey30)
ReservationState.CANCELED -> Pair(R.string.reservations_canceled, Error)
ReservationState.RESERVED -> Pair(R.string.reservations_reserved, Success)
ReservationState.RESERVED -> Pair(
if (isGift) R.string.reservations_gift_received else R.string.reservations_reserved,
Success
)
ReservationState.REFUNDED -> Pair(R.string.reservations_refunded, Error)
ReservationState.REGISTERING_GIFT -> Pair(R.string.reservations_registering_gift, Grey30)
ReservationState.UNDEFINED -> Pair(R.string.reservations_unknown, Error)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.nexters.boolti.presentation.reservationdetail

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.nexters.boolti.presentation.R
import com.nexters.boolti.presentation.theme.Grey95
import com.nexters.boolti.presentation.theme.KakaoYellow

@Composable
fun ResendGiftButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
TextButton(
onClick = onClick,
modifier = modifier
.fillMaxWidth()
.height(48.dp),
shape = RoundedCornerShape(4.dp),
colors = ButtonDefaults.outlinedButtonColors(containerColor = KakaoYellow),
contentPadding = PaddingValues(horizontal = 20.dp)
) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.CenterStart,
) {
Icon(
painter = painterResource(R.drawable.ic_kakaotalk), contentDescription = null,
modifier = Modifier.size(width = 20.dp, height = 20.dp),
tint = Color.Black,
)
Text(
stringResource(id = R.string.gift_resend_message),
modifier = Modifier.fillMaxWidth(),
style = MaterialTheme.typography.titleMedium,
color = Grey95,
textAlign = TextAlign.Center,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package com.nexters.boolti.presentation.screen.reservations
package com.nexters.boolti.presentation.reservationdetail

import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import com.nexters.boolti.presentation.screen.MainDestination
import com.nexters.boolti.presentation.screen.reservationId

fun NavGraphBuilder.ReservationDetailScreen(
navigateTo: (String) -> Unit,
popBackStack: () -> Unit,
) {
composable(
route = "${MainDestination.ReservationDetail.route}/{$reservationId}",
route = MainDestination.ReservationDetail.route,
arguments = MainDestination.ReservationDetail.arguments,
) {
ReservationDetailScreen(
onBackPressed = popBackStack,
navigateToRefund = { id -> navigateTo("${MainDestination.Refund.route}/$id") },
navigateToRefund = { id, isGift ->
navigateTo(MainDestination.Refund.createRoute(id = id, isGift = isGift))
},
)
}
}
Loading

0 comments on commit 2fd431c

Please sign in to comment.