Updated on 2026-08-14
This commit is contained in:
parent
b27ff31652
commit
ad0b09deae
24 changed files with 397 additions and 40 deletions
|
|
@ -97,6 +97,12 @@ interface TangemPayApi {
|
||||||
@Body body: ReissueCardRequest,
|
@Body body: ReissueCardRequest,
|
||||||
): ApiResponse<ReissueCardResponse>
|
): ApiResponse<ReissueCardResponse>
|
||||||
|
|
||||||
|
@POST("v1/customer/card/close")
|
||||||
|
suspend fun closeCard(
|
||||||
|
@Header("Authorization") authHeader: String,
|
||||||
|
@Body body: CloseCardRequest,
|
||||||
|
): ApiResponse<CloseCardResponse>
|
||||||
|
|
||||||
@POST("v1/customer/card/withdraw/data")
|
@POST("v1/customer/card/withdraw/data")
|
||||||
suspend fun getWithdrawData(
|
suspend fun getWithdrawData(
|
||||||
@Header("Authorization") authHeader: String,
|
@Header("Authorization") authHeader: String,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.tangem.datasource.api.pay.models.request
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class CloseCardRequest(
|
||||||
|
@Json(name = "card_id") val cardId: String,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.tangem.datasource.api.pay.models.response
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class CloseCardResponse(
|
||||||
|
@Json(name = "result") val result: Result,
|
||||||
|
) {
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Result(
|
||||||
|
@Json(name = "order_id") val orderId: String,
|
||||||
|
@Json(name = "status") val status: OrderResponse.Result.Status,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -3,8 +3,10 @@ package com.tangem.datasource.di
|
||||||
import com.tangem.datasource.local.datastore.RuntimeDataStore
|
import com.tangem.datasource.local.datastore.RuntimeDataStore
|
||||||
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
import com.tangem.datasource.local.visa.DefaultTangemPayCardFrozenStateStore
|
import com.tangem.datasource.local.visa.DefaultTangemPayCardFrozenStateStore
|
||||||
|
import com.tangem.datasource.local.visa.DefaultTangemPayCloseCardStore
|
||||||
import com.tangem.datasource.local.visa.DefaultTangemPayReissueCardStore
|
import com.tangem.datasource.local.visa.DefaultTangemPayReissueCardStore
|
||||||
import com.tangem.datasource.local.visa.TangemPayCardFrozenStateStore
|
import com.tangem.datasource.local.visa.TangemPayCardFrozenStateStore
|
||||||
|
import com.tangem.datasource.local.visa.TangemPayCloseCardStore
|
||||||
import com.tangem.datasource.local.visa.TangemPayReissueCardStore
|
import com.tangem.datasource.local.visa.TangemPayReissueCardStore
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
|
|
@ -32,4 +34,12 @@ internal object TangemPayStoresModule {
|
||||||
prefs = prefs,
|
prefs = prefs,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
fun provideTangemPayCloseCardStore(prefs: AppPreferencesStore): TangemPayCloseCardStore {
|
||||||
|
return DefaultTangemPayCloseCardStore(
|
||||||
|
prefs = prefs,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.tangem.datasource.local.visa
|
||||||
|
|
||||||
|
import androidx.datastore.preferences.core.edit
|
||||||
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
|
import com.tangem.datasource.local.preferences.AppPreferencesStore
|
||||||
|
import com.tangem.datasource.local.preferences.utils.getSyncOrNull
|
||||||
|
import com.tangem.datasource.local.preferences.utils.store
|
||||||
|
|
||||||
|
internal class DefaultTangemPayCloseCardStore(
|
||||||
|
private val prefs: AppPreferencesStore,
|
||||||
|
) : TangemPayCloseCardStore {
|
||||||
|
|
||||||
|
override suspend fun setCloseOrderId(cardId: String, orderId: String?) {
|
||||||
|
if (orderId == null) {
|
||||||
|
prefs.edit { it.remove(getCloseKey(cardId)) }
|
||||||
|
} else {
|
||||||
|
prefs.store(
|
||||||
|
key = getCloseKey(cardId),
|
||||||
|
value = orderId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getOrderId(cardId: String): String? {
|
||||||
|
return prefs.getSyncOrNull(key = getCloseKey(cardId))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCloseKey(cardId: String) = stringPreferencesKey("tangem_pay_close_card_$cardId")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.tangem.datasource.local.visa
|
||||||
|
|
||||||
|
interface TangemPayCloseCardStore {
|
||||||
|
|
||||||
|
suspend fun setCloseOrderId(cardId: String, orderId: String?)
|
||||||
|
|
||||||
|
suspend fun getOrderId(cardId: String): String?
|
||||||
|
}
|
||||||
|
|
@ -86,6 +86,6 @@ sealed interface PaymentAccountStatusValueDM {
|
||||||
@Json(name = "admin_daily_limit") val adminDailyLimit: SerializedBigDecimal?,
|
@Json(name = "admin_daily_limit") val adminDailyLimit: SerializedBigDecimal?,
|
||||||
@Json(name = "frozen_state") val frozenState: String,
|
@Json(name = "frozen_state") val frozenState: String,
|
||||||
@Json(name = "last_digits") val lastDigits: String,
|
@Json(name = "last_digits") val lastDigits: String,
|
||||||
@Json(name = "is_reissuing") val isReissuing: Boolean,
|
@Json(name = "state") val state: String,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimit
|
import com.tangem.domain.models.pay.TangemPayCardLimit
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimitData
|
import com.tangem.domain.models.pay.TangemPayCardLimitData
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -52,7 +53,7 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor(
|
||||||
adminDailyLimit = card.limit?.adminCardLimit?.amount,
|
adminDailyLimit = card.limit?.adminCardLimit?.amount,
|
||||||
frozenState = card.frozenState.toString(),
|
frozenState = card.frozenState.toString(),
|
||||||
lastDigits = card.lastDigits,
|
lastDigits = card.lastDigits,
|
||||||
isReissuing = card.isReissuing,
|
state = card.state.toString(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -108,7 +109,7 @@ internal class PaymentAccountStatusValueDMConverter @Inject constructor(
|
||||||
),
|
),
|
||||||
frozenState = TangemPayCardFrozenState.fromString(card.frozenState),
|
frozenState = TangemPayCardFrozenState.fromString(card.frozenState),
|
||||||
lastDigits = card.lastDigits,
|
lastDigits = card.lastDigits,
|
||||||
isReissuing = card.isReissuing,
|
state = TangemPayCardState.fromString(card.state),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import com.tangem.domain.pay.flow.PaymentAccountStatusProducer
|
||||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||||
import com.tangem.domain.pay.repository.*
|
import com.tangem.domain.pay.repository.*
|
||||||
import com.tangem.domain.pay.usecase.ChangeCardFrozenStateUseCase
|
import com.tangem.domain.pay.usecase.ChangeCardFrozenStateUseCase
|
||||||
|
import com.tangem.domain.pay.usecase.CloseTangemPayCardUseCase
|
||||||
import com.tangem.domain.pay.usecase.GetPaymentAccountCryptoCurrencyStatusUseCase
|
import com.tangem.domain.pay.usecase.GetPaymentAccountCryptoCurrencyStatusUseCase
|
||||||
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
import com.tangem.domain.pay.usecase.ProduceTangemPayInitialDataUseCase
|
||||||
import com.tangem.domain.pay.usecase.ReissueTangemPayCardUseCase
|
import com.tangem.domain.pay.usecase.ReissueTangemPayCardUseCase
|
||||||
|
|
@ -73,6 +74,10 @@ internal interface TangemPayDataModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
fun bindReissueCardRepository(repository: DefaultReissueCardRepository): TangemPayReissueCardRepository
|
fun bindReissueCardRepository(repository: DefaultReissueCardRepository): TangemPayReissueCardRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun bindCloseCardRepository(repository: DefaultCloseCardRepository): TangemPayCloseCardRepository
|
||||||
|
|
||||||
@Binds
|
@Binds
|
||||||
@Singleton
|
@Singleton
|
||||||
fun bindTangemPayCryptoCurrencyFactory(
|
fun bindTangemPayCryptoCurrencyFactory(
|
||||||
|
|
@ -220,5 +225,20 @@ internal interface TangemPayDataModule {
|
||||||
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
|
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideCloseTangemPayCardUseCase(
|
||||||
|
closeCardRepository: TangemPayCloseCardRepository,
|
||||||
|
startTangemPayOrderPollingUseCase: StartTangemPayOrderPollingUseCase,
|
||||||
|
appCoroutineScope: AppCoroutineScope,
|
||||||
|
paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||||
|
): CloseTangemPayCardUseCase {
|
||||||
|
return CloseTangemPayCardUseCase(
|
||||||
|
closeCardRepository = closeCardRepository,
|
||||||
|
startTangemPayOrderPollingUseCase = startTangemPayOrderPollingUseCase,
|
||||||
|
appCoroutineScope = appCoroutineScope,
|
||||||
|
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -23,7 +23,10 @@ import com.tangem.domain.pay.repository.OnboardingRepository
|
||||||
import com.tangem.domain.pay.repository.TangemPayReissueCardRepository
|
import com.tangem.domain.pay.repository.TangemPayReissueCardRepository
|
||||||
import com.tangem.domain.visa.error.VisaApiError
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
|
import com.tangem.domain.pay.model.isFinalStatus
|
||||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||||
|
import com.tangem.domain.pay.repository.TangemPayCloseCardRepository
|
||||||
import com.tangem.security.DeviceSecurityInfoProvider
|
import com.tangem.security.DeviceSecurityInfoProvider
|
||||||
import com.tangem.security.isSecurityExposed
|
import com.tangem.security.isSecurityExposed
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
|
@ -36,7 +39,7 @@ import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
private const val TAG = "PaymentAccountStatusFetcher"
|
private const val TAG = "PaymentAccountStatusFetcher"
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList", "LargeClass")
|
||||||
internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
||||||
private val paymentAccountStatusesStore: PaymentAccountStatusesStore,
|
private val paymentAccountStatusesStore: PaymentAccountStatusesStore,
|
||||||
private val onboardingRepository: OnboardingRepository,
|
private val onboardingRepository: OnboardingRepository,
|
||||||
|
|
@ -46,6 +49,7 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
||||||
private val tangemPayCurrencyFactory: TangemPayCurrencyFactory,
|
private val tangemPayCurrencyFactory: TangemPayCurrencyFactory,
|
||||||
private val eligibilityManager: TangemPayEligibilityManager,
|
private val eligibilityManager: TangemPayEligibilityManager,
|
||||||
private val reissueCardRepository: TangemPayReissueCardRepository,
|
private val reissueCardRepository: TangemPayReissueCardRepository,
|
||||||
|
private val closeCardRepository: TangemPayCloseCardRepository,
|
||||||
private val cardDetailsRepository: TangemPayCardDetailsRepository,
|
private val cardDetailsRepository: TangemPayCardDetailsRepository,
|
||||||
) : PaymentAccountStatusFetcher {
|
) : PaymentAccountStatusFetcher {
|
||||||
|
|
||||||
|
|
@ -299,16 +303,9 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
||||||
cardInfo: CustomerInfo.CardInfo,
|
cardInfo: CustomerInfo.CardInfo,
|
||||||
customerId: String,
|
customerId: String,
|
||||||
): PaymentAccountStatusValue {
|
): PaymentAccountStatusValue {
|
||||||
val reissueOrder = reissueCardRepository.getReissueOrderInfo(
|
val cardId = productInstance.cardId
|
||||||
userWalletId = userWalletId,
|
val cardState = getCardState(cardId, userWalletId)
|
||||||
cardId = productInstance.cardId,
|
val cardFrozenState = cardDetailsRepository.cardFrozenStateSync(cardId)
|
||||||
).getOrNull()
|
|
||||||
|
|
||||||
val isReissuing = reissueOrder != null &&
|
|
||||||
reissueOrder.orderStatus != OrderStatus.CANCELED &&
|
|
||||||
reissueOrder.orderStatus != OrderStatus.COMPLETED
|
|
||||||
|
|
||||||
val cardFrozenState = cardDetailsRepository.cardFrozenStateSync(productInstance.cardId)
|
|
||||||
val cryptoCurrency = tangemPayCurrencyFactory.create(userWalletId)
|
val cryptoCurrency = tangemPayCurrencyFactory.create(userWalletId)
|
||||||
return PaymentAccountStatusValue.Loaded(
|
return PaymentAccountStatusValue.Loaded(
|
||||||
source = StatusSource.ACTUAL,
|
source = StatusSource.ACTUAL,
|
||||||
|
|
@ -321,7 +318,7 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
||||||
cryptoCurrency = cryptoCurrency,
|
cryptoCurrency = cryptoCurrency,
|
||||||
cards = listOf(
|
cards = listOf(
|
||||||
TangemPayCard(
|
TangemPayCard(
|
||||||
id = productInstance.cardId,
|
id = cardId,
|
||||||
hasPinCode = cardInfo.isPinSet,
|
hasPinCode = cardInfo.isPinSet,
|
||||||
displayName = productInstance.displayName,
|
displayName = productInstance.displayName,
|
||||||
limit = TangemPayCardLimitData(
|
limit = TangemPayCardLimitData(
|
||||||
|
|
@ -334,12 +331,35 @@ internal class DefaultPaymentAccountStatusFetcher @Inject constructor(
|
||||||
productInstance.frozenState
|
productInstance.frozenState
|
||||||
},
|
},
|
||||||
lastDigits = cardInfo.lastFourDigits,
|
lastDigits = cardInfo.lastFourDigits,
|
||||||
isReissuing = isReissuing,
|
state = cardState,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun getCardState(cardId: String, userWalletId: UserWalletId): TangemPayCardState {
|
||||||
|
val closingOrderId = closeCardRepository.getCloseOrderId(userWalletId, cardId).getOrNull()
|
||||||
|
val reissueOrderId = reissueCardRepository.getReissueOrderId(userWalletId, cardId).getOrNull()
|
||||||
|
return if (closingOrderId != null) {
|
||||||
|
val order = cardDetailsRepository.getOrderInfo(userWalletId, closingOrderId).getOrNull()
|
||||||
|
if (order != null && order.orderStatus.isFinalStatus) {
|
||||||
|
closeCardRepository.setCloseOrderId(cardId, null)
|
||||||
|
TangemPayCardState.Active
|
||||||
|
} else {
|
||||||
|
TangemPayCardState.Closing
|
||||||
|
}
|
||||||
|
} else if (reissueOrderId != null) {
|
||||||
|
val order = cardDetailsRepository.getOrderInfo(userWalletId, reissueOrderId).getOrNull()
|
||||||
|
if (order != null && order.orderStatus.isFinalStatus) {
|
||||||
|
TangemPayCardState.Active
|
||||||
|
} else {
|
||||||
|
TangemPayCardState.Reissuing
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TangemPayCardState.Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun VisaApiError.mapToPaymentAccountStatus(userWalletId: UserWalletId): PaymentAccountStatusValue {
|
private suspend fun VisaApiError.mapToPaymentAccountStatus(userWalletId: UserWalletId): PaymentAccountStatusValue {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is VisaApiError.RefreshTokenExpired -> PaymentAccountStatusValue.Error.NotSynced
|
is VisaApiError.RefreshTokenExpired -> PaymentAccountStatusValue.Error.NotSynced
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.tangem.data.pay.repository
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import arrow.core.raise.either
|
||||||
|
import arrow.core.right
|
||||||
|
import com.tangem.core.error.UniversalError
|
||||||
|
import com.tangem.data.pay.util.OrderStatusConverter
|
||||||
|
import com.tangem.datasource.api.pay.TangemPayApi
|
||||||
|
import com.tangem.datasource.api.pay.models.request.CloseCardRequest
|
||||||
|
import com.tangem.datasource.local.visa.TangemPayCloseCardStore
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.TangemPayOrderInfo
|
||||||
|
import com.tangem.domain.pay.repository.TangemPayCloseCardRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
import com.tangem.utils.coroutines.runSuspendCatching
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class DefaultCloseCardRepository @Inject constructor(
|
||||||
|
private val tangemPayApi: TangemPayApi,
|
||||||
|
private val requestHelper: TangemPayRequestPerformer,
|
||||||
|
private val tangemPayCloseCardStore: TangemPayCloseCardStore,
|
||||||
|
) : TangemPayCloseCardRepository {
|
||||||
|
|
||||||
|
override suspend fun closeCard(
|
||||||
|
userWalletId: UserWalletId,
|
||||||
|
cardId: String,
|
||||||
|
): Either<VisaApiError, TangemPayOrderInfo> = either {
|
||||||
|
val response = requestHelper.performRequest(userWalletId) { authHeader ->
|
||||||
|
tangemPayApi.closeCard(
|
||||||
|
authHeader = authHeader,
|
||||||
|
body = CloseCardRequest(cardId = cardId),
|
||||||
|
)
|
||||||
|
}.bind()
|
||||||
|
TangemPayOrderInfo(
|
||||||
|
orderId = response.result.orderId,
|
||||||
|
orderStatus = OrderStatusConverter.convert(response.result.status),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun setCloseOrderId(cardId: String, orderId: String?): Either<UniversalError, Unit> =
|
||||||
|
runSuspendCatching {
|
||||||
|
tangemPayCloseCardStore.setCloseOrderId(cardId, orderId)
|
||||||
|
}.fold(
|
||||||
|
onSuccess = { Unit.right() },
|
||||||
|
onFailure = { Either.Left(VisaApiError.Unspecified) },
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getCloseOrderId(userWalletId: UserWalletId, cardId: String): Either<UniversalError, String?> =
|
||||||
|
either {
|
||||||
|
runSuspendCatching { tangemPayCloseCardStore.getOrderId(cardId) }.getOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,6 @@ import com.tangem.datasource.local.visa.TangemPayReissueCardStore
|
||||||
import com.tangem.domain.models.pay.TangemPayReissueCardFee
|
import com.tangem.domain.models.pay.TangemPayReissueCardFee
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.pay.model.TangemPayOrderInfo
|
import com.tangem.domain.pay.model.TangemPayOrderInfo
|
||||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
|
||||||
import com.tangem.domain.pay.repository.TangemPayReissueCardRepository
|
import com.tangem.domain.pay.repository.TangemPayReissueCardRepository
|
||||||
import com.tangem.domain.visa.error.VisaApiError
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
import com.tangem.utils.coroutines.runSuspendCatching
|
import com.tangem.utils.coroutines.runSuspendCatching
|
||||||
|
|
@ -21,7 +20,6 @@ internal class DefaultReissueCardRepository @Inject constructor(
|
||||||
private val tangemPayApi: TangemPayApi,
|
private val tangemPayApi: TangemPayApi,
|
||||||
private val requestHelper: TangemPayRequestPerformer,
|
private val requestHelper: TangemPayRequestPerformer,
|
||||||
private val tangemPayReissueCardStore: TangemPayReissueCardStore,
|
private val tangemPayReissueCardStore: TangemPayReissueCardStore,
|
||||||
private val cardDetailsRepository: TangemPayCardDetailsRepository,
|
|
||||||
) : TangemPayReissueCardRepository {
|
) : TangemPayReissueCardRepository {
|
||||||
|
|
||||||
override suspend fun getReissueCardFee(userWalletId: UserWalletId): Either<VisaApiError, TangemPayReissueCardFee> =
|
override suspend fun getReissueCardFee(userWalletId: UserWalletId): Either<VisaApiError, TangemPayReissueCardFee> =
|
||||||
|
|
@ -74,17 +72,11 @@ internal class DefaultReissueCardRepository @Inject constructor(
|
||||||
onFailure = { Either.Left(VisaApiError.Unspecified) },
|
onFailure = { Either.Left(VisaApiError.Unspecified) },
|
||||||
)
|
)
|
||||||
|
|
||||||
override suspend fun getReissueOrderInfo(
|
override suspend fun getReissueOrderId(
|
||||||
userWalletId: UserWalletId,
|
userWalletId: UserWalletId,
|
||||||
cardId: String,
|
cardId: String,
|
||||||
): Either<UniversalError, TangemPayOrderInfo?> = either {
|
): Either<UniversalError, String?> = either {
|
||||||
val orderId = runSuspendCatching { tangemPayReissueCardStore.getOrderId(cardId) }.getOrNull()
|
runSuspendCatching { tangemPayReissueCardStore.getOrderId(cardId) }.getOrNull()
|
||||||
|
|
||||||
if (orderId == null) {
|
|
||||||
return null.right()
|
|
||||||
}
|
|
||||||
|
|
||||||
cardDetailsRepository.getOrderInfo(userWalletId, orderId).bind()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import kotlinx.serialization.Serializable
|
||||||
* @property limit spending limit configuration for the card; `null` if not configured or not yet loaded.
|
* @property limit spending limit configuration for the card; `null` if not configured or not yet loaded.
|
||||||
* @property frozenState whether the card is currently frozen (blocked for payments).
|
* @property frozenState whether the card is currently frozen (blocked for payments).
|
||||||
* @property lastDigits The last four digits of the card number.
|
* @property lastDigits The last four digits of the card number.
|
||||||
|
* @property state current lifecycle state of the card.
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class TangemPayCard(
|
data class TangemPayCard(
|
||||||
|
|
@ -22,7 +23,7 @@ data class TangemPayCard(
|
||||||
@SerialName("limit") val limit: TangemPayCardLimitData?,
|
@SerialName("limit") val limit: TangemPayCardLimitData?,
|
||||||
@SerialName("frozen_state") val frozenState: TangemPayCardFrozenState,
|
@SerialName("frozen_state") val frozenState: TangemPayCardFrozenState,
|
||||||
@SerialName("last_digits") val lastDigits: String,
|
@SerialName("last_digits") val lastDigits: String,
|
||||||
@SerialName("is_reissuing") val isReissuing: Boolean,
|
@SerialName("state") val state: TangemPayCardState,
|
||||||
)
|
)
|
||||||
|
|
||||||
val TangemPayCard.isFrozen
|
val TangemPayCard.isFrozen
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.tangem.domain.models.pay
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle state of a Tangem Pay card.
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
enum class TangemPayCardState {
|
||||||
|
/** Card is operational and ready to use. */
|
||||||
|
@SerialName("Active")
|
||||||
|
Active,
|
||||||
|
|
||||||
|
/** A reissue order is in progress; the card is being replaced. */
|
||||||
|
@SerialName("Reissuing")
|
||||||
|
Reissuing,
|
||||||
|
|
||||||
|
/** A close order is in progress; the card is being closed. */
|
||||||
|
@SerialName("Closing")
|
||||||
|
Closing,
|
||||||
|
;
|
||||||
|
|
||||||
|
override fun toString() = when (this) {
|
||||||
|
Active -> "Active"
|
||||||
|
Reissuing -> "Reissuing"
|
||||||
|
Closing -> "Closing"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String) = when (value.lowercase(Locale.US)) {
|
||||||
|
"reissuing" -> Reissuing
|
||||||
|
"closing" -> Closing
|
||||||
|
else -> Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.tangem.domain.pay.repository
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import com.tangem.core.error.UniversalError
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.TangemPayOrderInfo
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
|
||||||
|
interface TangemPayCloseCardRepository {
|
||||||
|
|
||||||
|
suspend fun closeCard(userWalletId: UserWalletId, cardId: String): Either<VisaApiError, TangemPayOrderInfo>
|
||||||
|
|
||||||
|
suspend fun setCloseOrderId(cardId: String, orderId: String?): Either<UniversalError, Unit>
|
||||||
|
|
||||||
|
suspend fun getCloseOrderId(userWalletId: UserWalletId, cardId: String): Either<UniversalError, String?>
|
||||||
|
}
|
||||||
|
|
@ -15,8 +15,5 @@ interface TangemPayReissueCardRepository {
|
||||||
|
|
||||||
suspend fun storeReissueOrderId(cardId: String, orderId: String): Either<UniversalError, Unit>
|
suspend fun storeReissueOrderId(cardId: String, orderId: String): Either<UniversalError, Unit>
|
||||||
|
|
||||||
suspend fun getReissueOrderInfo(
|
suspend fun getReissueOrderId(userWalletId: UserWalletId, cardId: String): Either<UniversalError, String?>
|
||||||
userWalletId: UserWalletId,
|
|
||||||
cardId: String,
|
|
||||||
): Either<UniversalError, TangemPayOrderInfo?>
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.tangem.domain.pay.usecase
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import arrow.core.raise.either
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||||
|
import com.tangem.domain.pay.model.OrderStatus
|
||||||
|
import com.tangem.domain.pay.repository.TangemPayCloseCardRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
import com.tangem.utils.coroutines.AppCoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class CloseTangemPayCardUseCase(
|
||||||
|
private val closeCardRepository: TangemPayCloseCardRepository,
|
||||||
|
private val startTangemPayOrderPollingUseCase: StartTangemPayOrderPollingUseCase,
|
||||||
|
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher,
|
||||||
|
private val appCoroutineScope: AppCoroutineScope,
|
||||||
|
) {
|
||||||
|
suspend operator fun invoke(userWalletId: UserWalletId, cardId: String): Either<VisaApiError, Unit> = either {
|
||||||
|
val order = closeCardRepository.closeCard(userWalletId, cardId).bind()
|
||||||
|
|
||||||
|
if (order.orderStatus == OrderStatus.CANCELED) {
|
||||||
|
raise(VisaApiError.Unspecified)
|
||||||
|
}
|
||||||
|
|
||||||
|
closeCardRepository.setCloseOrderId(cardId, order.orderId)
|
||||||
|
paymentAccountStatusFetcher.invoke(userWalletId)
|
||||||
|
|
||||||
|
appCoroutineScope.launch {
|
||||||
|
startTangemPayOrderPollingUseCase(order, userWalletId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.tangem.domain.pay.usecase
|
||||||
|
|
||||||
|
import arrow.core.left
|
||||||
|
import arrow.core.right
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import com.tangem.common.test.TestAppCoroutineScope
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.flow.PaymentAccountStatusFetcher
|
||||||
|
import com.tangem.domain.pay.model.OrderStatus
|
||||||
|
import com.tangem.domain.pay.model.TangemPayOrderInfo
|
||||||
|
import com.tangem.domain.pay.repository.TangemPayCloseCardRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
import io.mockk.coEvery
|
||||||
|
import io.mockk.coVerify
|
||||||
|
import io.mockk.coVerifyOrder
|
||||||
|
import io.mockk.mockk
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
internal class CloseTangemPayCardUseCaseTest {
|
||||||
|
|
||||||
|
private val closeCardRepository: TangemPayCloseCardRepository = mockk(relaxUnitFun = true)
|
||||||
|
private val startPollingUseCase: StartTangemPayOrderPollingUseCase = mockk()
|
||||||
|
private val paymentAccountStatusFetcher: PaymentAccountStatusFetcher = mockk()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN closeCard fails WHEN invoke THEN returns Left and skips store, fetch and polling`() = runTest {
|
||||||
|
val useCase = createUseCase()
|
||||||
|
coEvery { closeCardRepository.closeCard(USER_WALLET_ID, CARD_ID) } returns VisaApiError.Unspecified.left()
|
||||||
|
|
||||||
|
val result = useCase(USER_WALLET_ID, CARD_ID)
|
||||||
|
|
||||||
|
assertThat(result.isLeft()).isTrue()
|
||||||
|
coVerify(exactly = 0) { closeCardRepository.setCloseOrderId(any(), any()) }
|
||||||
|
coVerify(exactly = 0) { paymentAccountStatusFetcher.invoke(any<UserWalletId>()) }
|
||||||
|
coVerify(exactly = 0) { startPollingUseCase(any(), any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN closeCard returns CANCELED order WHEN invoke THEN returns Left and skips store, fetch and polling`() =
|
||||||
|
runTest {
|
||||||
|
val useCase = createUseCase()
|
||||||
|
val order = TangemPayOrderInfo(ORDER_ID, OrderStatus.CANCELED)
|
||||||
|
coEvery { closeCardRepository.closeCard(USER_WALLET_ID, CARD_ID) } returns order.right()
|
||||||
|
|
||||||
|
val result = useCase(USER_WALLET_ID, CARD_ID)
|
||||||
|
|
||||||
|
assertThat(result.isLeft()).isTrue()
|
||||||
|
coVerify(exactly = 0) { closeCardRepository.setCloseOrderId(any(), any()) }
|
||||||
|
coVerify(exactly = 0) { paymentAccountStatusFetcher.invoke(any<UserWalletId>()) }
|
||||||
|
coVerify(exactly = 0) { startPollingUseCase(any(), any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN closeCard returns PROCESSING order WHEN invoke THEN stores order id, fetches status and starts polling`() =
|
||||||
|
runTest {
|
||||||
|
val useCase = createUseCase()
|
||||||
|
val order = TangemPayOrderInfo(ORDER_ID, OrderStatus.PROCESSING)
|
||||||
|
coEvery { closeCardRepository.closeCard(USER_WALLET_ID, CARD_ID) } returns order.right()
|
||||||
|
coEvery { closeCardRepository.setCloseOrderId(CARD_ID, ORDER_ID) } returns Unit.right()
|
||||||
|
coEvery { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) } returns Unit.right()
|
||||||
|
coEvery { startPollingUseCase(order, USER_WALLET_ID) } returns true
|
||||||
|
|
||||||
|
val result = useCase(USER_WALLET_ID, CARD_ID)
|
||||||
|
|
||||||
|
assertThat(result.isRight()).isTrue()
|
||||||
|
coVerifyOrder {
|
||||||
|
closeCardRepository.setCloseOrderId(CARD_ID, ORDER_ID)
|
||||||
|
paymentAccountStatusFetcher.invoke(USER_WALLET_ID)
|
||||||
|
startPollingUseCase(order, USER_WALLET_ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN closeCard returns COMPLETED order WHEN invoke THEN stores order id, fetches status and starts polling`() =
|
||||||
|
runTest {
|
||||||
|
val useCase = createUseCase()
|
||||||
|
val order = TangemPayOrderInfo(ORDER_ID, OrderStatus.COMPLETED)
|
||||||
|
coEvery { closeCardRepository.closeCard(USER_WALLET_ID, CARD_ID) } returns order.right()
|
||||||
|
coEvery { closeCardRepository.setCloseOrderId(CARD_ID, ORDER_ID) } returns Unit.right()
|
||||||
|
coEvery { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) } returns Unit.right()
|
||||||
|
coEvery { startPollingUseCase(order, USER_WALLET_ID) } returns true
|
||||||
|
|
||||||
|
val result = useCase(USER_WALLET_ID, CARD_ID)
|
||||||
|
|
||||||
|
assertThat(result.isRight()).isTrue()
|
||||||
|
coVerify(exactly = 1) { closeCardRepository.setCloseOrderId(CARD_ID, ORDER_ID) }
|
||||||
|
coVerify(exactly = 1) { paymentAccountStatusFetcher.invoke(USER_WALLET_ID) }
|
||||||
|
coVerify(exactly = 1) { startPollingUseCase(order, USER_WALLET_ID) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createUseCase() = CloseTangemPayCardUseCase(
|
||||||
|
closeCardRepository = closeCardRepository,
|
||||||
|
startTangemPayOrderPollingUseCase = startPollingUseCase,
|
||||||
|
paymentAccountStatusFetcher = paymentAccountStatusFetcher,
|
||||||
|
appCoroutineScope = TestAppCoroutineScope(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val USER_WALLET_ID = UserWalletId("aabbcc112233")
|
||||||
|
const val CARD_ID = "card-test-id"
|
||||||
|
const val ORDER_ID = "order-test-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import com.tangem.core.ui.message.SnackbarMessage
|
||||||
import com.tangem.domain.models.StatusSource
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||||
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||||
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
||||||
|
|
@ -95,7 +96,7 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
|
||||||
val status = state.value
|
val status = state.value
|
||||||
if (status is PaymentAccountStatusValue.Loaded && status.source == StatusSource.ACTUAL) {
|
if (status is PaymentAccountStatusValue.Loaded && status.source == StatusSource.ACTUAL) {
|
||||||
val card = state.findCard(initialCard.id, params.initialStatus) ?: return@onEach
|
val card = state.findCard(initialCard.id, params.initialStatus) ?: return@onEach
|
||||||
if (card.isReissuing) {
|
if (card.state != TangemPayCardState.Active) {
|
||||||
requestHide()
|
requestHide()
|
||||||
}
|
}
|
||||||
card.displayName?.let { uiState.update(TangemPayCardDetailsUpdateNameTransformer(it)) }
|
card.displayName?.let { uiState.update(TangemPayCardDetailsUpdateNameTransformer(it)) }
|
||||||
|
|
@ -103,7 +104,7 @@ internal class TangemPayCardDetailsBlockModel @Inject constructor(
|
||||||
uiState.copy(
|
uiState.copy(
|
||||||
numberShort = "${StringsSigns.ASTERISK}${card.lastDigits}",
|
numberShort = "${StringsSigns.ASTERISK}${card.lastDigits}",
|
||||||
cardFrozenState = card.frozenState,
|
cardFrozenState = card.frozenState,
|
||||||
isActionsAvailable = !card.isReissuing,
|
isActionsAvailable = card.state == TangemPayCardState.Active,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
subscribeToCardFrozenState(card.id)
|
subscribeToCardFrozenState(card.id)
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import com.tangem.domain.models.TokenReceiveConfig
|
||||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||||
import com.tangem.domain.models.pay.TangemPayCard
|
import com.tangem.domain.models.pay.TangemPayCard
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.models.pay.isFrozen
|
import com.tangem.domain.models.pay.isFrozen
|
||||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||||
import com.tangem.domain.pay.model.TangemPayTopUpData
|
import com.tangem.domain.pay.model.TangemPayTopUpData
|
||||||
|
|
@ -125,7 +126,7 @@ internal class TangemPayCardPageModel @Inject constructor(
|
||||||
dailyLimitState = dailyLimitState,
|
dailyLimitState = dailyLimitState,
|
||||||
settings = buildSettings(card),
|
settings = buildSettings(card),
|
||||||
settingsV2 = buildSettingsV2(card),
|
settingsV2 = buildSettingsV2(card),
|
||||||
isReissueInProgress = card.isReissuing,
|
isReissueInProgress = card.state == TangemPayCardState.Reissuing,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||||
import com.tangem.domain.pay.repository.TangemPayWithdrawRepository
|
import com.tangem.domain.pay.repository.TangemPayWithdrawRepository
|
||||||
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
import com.tangem.domain.tangempay.TangemPayAnalyticsEvents
|
||||||
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.visa.model.TangemPayTxHistoryItem
|
import com.tangem.domain.visa.model.TangemPayTxHistoryItem
|
||||||
import com.tangem.features.tangempay.TangemPayConstants
|
import com.tangem.features.tangempay.TangemPayConstants
|
||||||
import com.tangem.features.tangempay.components.AddFundsListener
|
import com.tangem.features.tangempay.components.AddFundsListener
|
||||||
|
|
@ -101,7 +102,7 @@ internal class TangemPayDetailsModel @Inject constructor(
|
||||||
stateFactory.getInitialState(
|
stateFactory.getInitialState(
|
||||||
isTangemPayDeactivated = isTangemPayDeactivated,
|
isTangemPayDeactivated = isTangemPayDeactivated,
|
||||||
cardNumberEnd = firstCard?.lastDigits.orEmpty(),
|
cardNumberEnd = firstCard?.lastDigits.orEmpty(),
|
||||||
isReissuing = firstCard?.isReissuing ?: false,
|
isReissuing = firstCard == null || firstCard.state != TangemPayCardState.Active,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.features.tangempay.model.transformers
|
package com.tangem.features.tangempay.model.transformers
|
||||||
|
|
||||||
import com.tangem.domain.models.pay.TangemPayCard
|
import com.tangem.domain.models.pay.TangemPayCard
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState
|
import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState
|
||||||
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
import com.tangem.features.tangempay.entity.TangemPayDetailsUM
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
|
|
@ -15,7 +16,7 @@ internal class TangemPayCardDataTransformer(
|
||||||
val updatedCard = TangemPayDetailsBalanceBlockState.Card(
|
val updatedCard = TangemPayDetailsBalanceBlockState.Card(
|
||||||
lastDigits = card.lastDigits,
|
lastDigits = card.lastDigits,
|
||||||
onClick = onCardClick,
|
onClick = onCardClick,
|
||||||
isReissuing = card.isReissuing,
|
isReissuing = card.state != TangemPayCardState.Active,
|
||||||
)
|
)
|
||||||
val cardsBlockState = prevState.balanceBlockState.cardsBlockState?.copy(
|
val cardsBlockState = prevState.balanceBlockState.cardsBlockState?.copy(
|
||||||
cards = persistentListOf(updatedCard),
|
cards = persistentListOf(updatedCard),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import com.tangem.domain.models.pay.TangemPayCardFrozenState
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimit
|
import com.tangem.domain.models.pay.TangemPayCardLimit
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimitData
|
import com.tangem.domain.models.pay.TangemPayCardLimitData
|
||||||
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
import com.tangem.domain.models.pay.TangemPayCardLimitPeriod
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.domain.models.wallet.UserWalletId
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
import com.tangem.domain.pay.flow.PaymentAccountStatusSupplier
|
||||||
import com.tangem.domain.pay.usecase.SetTangemPayCardLimitUseCase
|
import com.tangem.domain.pay.usecase.SetTangemPayCardLimitUseCase
|
||||||
|
|
@ -49,7 +50,7 @@ internal class TangemPayCardLimitSetupModelTest {
|
||||||
frozenState = TangemPayCardFrozenState.Unfrozen,
|
frozenState = TangemPayCardFrozenState.Unfrozen,
|
||||||
lastDigits = "1234",
|
lastDigits = "1234",
|
||||||
limit = null,
|
limit = null,
|
||||||
isReissuing = false,
|
state = TangemPayCardState.Active,
|
||||||
)
|
)
|
||||||
|
|
||||||
private val initialStatus: AccountStatus.Payment = AccountStatus.Payment(
|
private val initialStatus: AccountStatus.Payment = AccountStatus.Payment(
|
||||||
|
|
@ -79,7 +80,7 @@ internal class TangemPayCardLimitSetupModelTest {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
isReissuing = false,
|
state = TangemPayCardState.Active,
|
||||||
)
|
)
|
||||||
val statusWithLimit: PaymentAccountStatusValue.Loaded = mockk(relaxed = true) {
|
val statusWithLimit: PaymentAccountStatusValue.Loaded = mockk(relaxed = true) {
|
||||||
every { source } returns StatusSource.ACTUAL
|
every { source } returns StatusSource.ACTUAL
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.models.account.AccountStatus
|
import com.tangem.domain.models.account.AccountStatus
|
||||||
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
import com.tangem.domain.models.account.PaymentAccountStatusValue
|
||||||
import com.tangem.domain.models.kyc.KycStatus
|
import com.tangem.domain.models.kyc.KycStatus
|
||||||
|
import com.tangem.domain.models.pay.TangemPayCardState
|
||||||
import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
|
import com.tangem.feature.wallet.child.wallet.model.intents.TangemPayIntents
|
||||||
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
import com.tangem.features.tangempay.entity.TangemPayMainUM
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
|
|
@ -67,7 +68,7 @@ internal class TangemPayMainBlockConverter(
|
||||||
is PaymentAccountStatusValue.Loaded -> {
|
is PaymentAccountStatusValue.Loaded -> {
|
||||||
val card = statusValue.cards.firstOrNull() ?: return TangemPayMainUM.TemporaryUnavailable
|
val card = statusValue.cards.firstOrNull() ?: return TangemPayMainUM.TemporaryUnavailable
|
||||||
TangemPayMainUM.Content(
|
TangemPayMainUM.Content(
|
||||||
subtitle = if (card.isReissuing) {
|
subtitle = if (card.state == TangemPayCardState.Reissuing) {
|
||||||
resourceReference(R.string.tangempay_status_replacing)
|
resourceReference(R.string.tangempay_status_replacing)
|
||||||
} else {
|
} else {
|
||||||
stringReference("*${card.lastDigits}")
|
stringReference("*${card.lastDigits}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue