Updated on 2026-08-14
This commit is contained in:
parent
76cfb2e462
commit
5ca696d677
17 changed files with 431 additions and 0 deletions
|
|
@ -178,5 +178,9 @@
|
||||||
{
|
{
|
||||||
"name": "AND_16080_TRON_DEX_SWAP_ENABLED",
|
"name": "AND_16080_TRON_DEX_SWAP_ENABLED",
|
||||||
"version": "undefined"
|
"version": "undefined"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "TWI_1192_TANGEM_PAY_CASHBACK_ENABLED",
|
||||||
|
"version": "undefined"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -187,4 +187,7 @@ interface TangemPayApi {
|
||||||
@Body body: UpdateCardRequest,
|
@Body body: UpdateCardRequest,
|
||||||
@Path("card_id") cardId: String,
|
@Path("card_id") cardId: String,
|
||||||
): ApiResponse<UpdateCardDisplayNameResponse>
|
): ApiResponse<UpdateCardDisplayNameResponse>
|
||||||
|
|
||||||
|
@GET("v1/customer/cashback/summary")
|
||||||
|
suspend fun getCashbackSummary(@Header("Authorization") authHeader: String): ApiResponse<CashbackSummaryResponse>
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.tangem.datasource.api.pay.models.response
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response from `GET /v1/customer/cashback/summary`.
|
||||||
|
*
|
||||||
|
* When [cashbackProgramStatus] is not `enabled`, the amount/period fields may be omitted.
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class CashbackSummaryResponse(
|
||||||
|
@Json(name = "cashback_program_status") val cashbackProgramStatus: String,
|
||||||
|
@Json(name = "cashback_display_mode") val cashbackDisplayMode: String?,
|
||||||
|
@Json(name = "period") val period: Period?,
|
||||||
|
@Json(name = "confirmed_amount") val confirmedAmount: BigDecimal?,
|
||||||
|
@Json(name = "pending_amount") val pendingAmount: BigDecimal?,
|
||||||
|
@Json(name = "currency") val currency: String?,
|
||||||
|
) {
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Period(
|
||||||
|
@Json(name = "year") val year: Int,
|
||||||
|
@Json(name = "month") val month: Int,
|
||||||
|
@Json(name = "payout_start_date") val payoutStartDate: String?,
|
||||||
|
@Json(name = "payout_end_date") val payoutEndDate: String?,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -301,6 +301,11 @@ internal interface TangemPayDataModule {
|
||||||
return GetCustomerOffersUseCase(customerOffersRepository)
|
return GetCustomerOffersUseCase(customerOffersRepository)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideGetCashbackSummaryUseCase(cashbackRepository: CashbackRepository): GetCashbackSummaryUseCase {
|
||||||
|
return GetCashbackSummaryUseCase(cashbackRepository)
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideCheckOrderConflictUseCase(
|
fun provideCheckOrderConflictUseCase(
|
||||||
customerOrderRepository: CustomerOrderRepository,
|
customerOrderRepository: CustomerOrderRepository,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.tangem.data.pay.repository
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import com.tangem.data.pay.util.CashbackSummaryConverter
|
||||||
|
import com.tangem.datasource.api.pay.TangemPayApi
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.pay.repository.CashbackRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
internal class DefaultCashbackRepository @Inject constructor(
|
||||||
|
private val tangemPayApi: TangemPayApi,
|
||||||
|
private val requestHelper: TangemPayRequestPerformer,
|
||||||
|
) : CashbackRepository {
|
||||||
|
|
||||||
|
override suspend fun getCashbackSummary(userWalletId: UserWalletId): Either<VisaApiError, CashbackSummary> {
|
||||||
|
return requestHelper.performRequest(userWalletId) { authHeader ->
|
||||||
|
tangemPayApi.getCashbackSummary(authHeader = authHeader)
|
||||||
|
}.map(CashbackSummaryConverter::convert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.tangem.data.pay.util
|
||||||
|
|
||||||
|
import com.tangem.datasource.api.pay.models.response.CashbackSummaryResponse
|
||||||
|
import com.tangem.domain.pay.model.CashbackDisplayMode
|
||||||
|
import com.tangem.domain.pay.model.CashbackProgramStatus
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.pay.model.TangemPayCashback
|
||||||
|
import com.tangem.utils.converter.Converter
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
/** Maps [CashbackSummaryResponse] (BFF) to the domain [CashbackSummary]. */
|
||||||
|
internal object CashbackSummaryConverter : Converter<CashbackSummaryResponse, CashbackSummary> {
|
||||||
|
|
||||||
|
override fun convert(value: CashbackSummaryResponse): CashbackSummary {
|
||||||
|
return when (CashbackProgramStatus.fromString(value.cashbackProgramStatus)) {
|
||||||
|
CashbackProgramStatus.ENABLED -> toEnabled(value)
|
||||||
|
CashbackProgramStatus.DEACTIVATED -> CashbackSummary.Deactivated
|
||||||
|
CashbackProgramStatus.DISABLED -> CashbackSummary.Disabled
|
||||||
|
CashbackProgramStatus.UNKNOWN -> CashbackSummary.Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toEnabled(value: CashbackSummaryResponse): CashbackSummary {
|
||||||
|
val period = value.period ?: return CashbackSummary.Unknown
|
||||||
|
val payoutStart = period.payoutStartDate?.let(DateTime::parse) ?: return CashbackSummary.Unknown
|
||||||
|
val payoutEnd = period.payoutEndDate?.let(DateTime::parse) ?: return CashbackSummary.Unknown
|
||||||
|
|
||||||
|
return CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.fromString(value.cashbackDisplayMode),
|
||||||
|
cashback = TangemPayCashback(
|
||||||
|
confirmedAmount = value.confirmedAmount ?: BigDecimal.ZERO,
|
||||||
|
currency = value.currency.orEmpty(),
|
||||||
|
period = TangemPayCashback.Period(
|
||||||
|
year = period.year,
|
||||||
|
month = period.month,
|
||||||
|
payoutStart = payoutStart,
|
||||||
|
payoutEnd = payoutEnd,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pendingAmount = value.pendingAmount ?: BigDecimal.ZERO,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package com.tangem.data.pay.di
|
package com.tangem.data.pay.di
|
||||||
|
|
||||||
|
import com.tangem.data.pay.repository.MockAwareCashbackRepository
|
||||||
import com.tangem.data.pay.repository.MockAwareOnboardingRepository
|
import com.tangem.data.pay.repository.MockAwareOnboardingRepository
|
||||||
import com.tangem.data.pay.repository.MockAwareTangemPayCardDetailsRepository
|
import com.tangem.data.pay.repository.MockAwareTangemPayCardDetailsRepository
|
||||||
|
import com.tangem.domain.pay.repository.CashbackRepository
|
||||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
|
|
@ -21,4 +23,8 @@ internal interface TangemPayDataMockedModule {
|
||||||
@Binds
|
@Binds
|
||||||
@Singleton
|
@Singleton
|
||||||
fun bindCardDetailsRepository(repository: MockAwareTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
fun bindCardDetailsRepository(repository: MockAwareTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun bindCashbackRepository(repository: MockAwareCashbackRepository): CashbackRepository
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.tangem.data.pay.repository
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import arrow.core.right
|
||||||
|
import com.tangem.datasource.api.common.config.ApiConfig
|
||||||
|
import com.tangem.datasource.api.common.config.ApiEnvironment
|
||||||
|
import com.tangem.datasource.api.common.config.managers.ApiConfigsManager
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.CashbackDisplayMode
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.pay.model.TangemPayCashback
|
||||||
|
import com.tangem.domain.pay.repository.CashbackRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import java.math.BigDecimal
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
/** In MOCK env returns a canned cashback summary; otherwise delegates to [DefaultCashbackRepository]. */
|
||||||
|
@Singleton
|
||||||
|
internal class MockAwareCashbackRepository @Inject constructor(
|
||||||
|
private val real: DefaultCashbackRepository,
|
||||||
|
private val apiConfigsManager: ApiConfigsManager,
|
||||||
|
) : CashbackRepository {
|
||||||
|
|
||||||
|
private val isMockMode: Boolean
|
||||||
|
get() = apiConfigsManager
|
||||||
|
.getEnvironmentConfig(ApiConfig.ID.TangemPay)
|
||||||
|
.environment == ApiEnvironment.MOCK
|
||||||
|
|
||||||
|
override suspend fun getCashbackSummary(userWalletId: UserWalletId): Either<VisaApiError, CashbackSummary> {
|
||||||
|
if (isMockMode) return MOCK_SUMMARY.right()
|
||||||
|
return real.getCashbackSummary(userWalletId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
val MOCK_SUMMARY = CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.FULL,
|
||||||
|
cashback = TangemPayCashback(
|
||||||
|
confirmedAmount = BigDecimal("22.54"),
|
||||||
|
currency = "USD",
|
||||||
|
period = TangemPayCashback.Period(
|
||||||
|
year = 2026,
|
||||||
|
month = 6,
|
||||||
|
payoutStart = DateTime.parse("2026-07-02"),
|
||||||
|
payoutEnd = DateTime.parse("2026-07-05"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
pendingAmount = BigDecimal("13.65"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package com.tangem.data.pay.di
|
package com.tangem.data.pay.di
|
||||||
|
|
||||||
|
import com.tangem.data.pay.repository.DefaultCashbackRepository
|
||||||
import com.tangem.data.pay.repository.DefaultOnboardingRepository
|
import com.tangem.data.pay.repository.DefaultOnboardingRepository
|
||||||
import com.tangem.data.pay.repository.DefaultTangemPayCardDetailsRepository
|
import com.tangem.data.pay.repository.DefaultTangemPayCardDetailsRepository
|
||||||
|
import com.tangem.domain.pay.repository.CashbackRepository
|
||||||
import com.tangem.domain.pay.repository.OnboardingRepository
|
import com.tangem.domain.pay.repository.OnboardingRepository
|
||||||
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
import com.tangem.domain.pay.repository.TangemPayCardDetailsRepository
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
|
|
@ -21,4 +23,8 @@ internal interface TangemPayDataProductionModule {
|
||||||
@Binds
|
@Binds
|
||||||
@Singleton
|
@Singleton
|
||||||
fun bindCardDetailsRepository(repository: DefaultTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
fun bindCardDetailsRepository(repository: DefaultTangemPayCardDetailsRepository): TangemPayCardDetailsRepository
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun bindCashbackRepository(repository: DefaultCashbackRepository): CashbackRepository
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.tangem.data.pay.util
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import com.tangem.datasource.api.pay.models.response.CashbackSummaryResponse
|
||||||
|
import com.tangem.domain.pay.model.CashbackDisplayMode
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.pay.model.TangemPayCashback
|
||||||
|
import org.joda.time.DateTime
|
||||||
|
import org.junit.jupiter.api.TestInstance
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||||
|
internal class CashbackSummaryConverterTest {
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("provideTestModels")
|
||||||
|
fun convert(model: ConvertModel) {
|
||||||
|
// Act
|
||||||
|
val actual = CashbackSummaryConverter.convert(model.response)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
assertThat(actual).isEqualTo(model.expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("LongMethod")
|
||||||
|
private fun provideTestModels() = listOf(
|
||||||
|
ConvertModel(
|
||||||
|
name = "enabled + full -> Enabled(FULL)",
|
||||||
|
response = createResponse(status = "enabled", displayMode = "full"),
|
||||||
|
expected = CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.FULL,
|
||||||
|
cashback = expectedCashback(),
|
||||||
|
pendingAmount = BigDecimal("13.65"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "enabled + alt_block -> Enabled(ALT_BLOCK)",
|
||||||
|
response = createResponse(status = "enabled", displayMode = "alt_block"),
|
||||||
|
expected = CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.ALT_BLOCK,
|
||||||
|
cashback = expectedCashback(),
|
||||||
|
pendingAmount = BigDecimal("13.65"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "enabled + missing display mode -> Enabled(FULL)",
|
||||||
|
response = createResponse(status = "enabled", displayMode = null),
|
||||||
|
expected = CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.FULL,
|
||||||
|
cashback = expectedCashback(),
|
||||||
|
pendingAmount = BigDecimal("13.65"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "enabled + zero amounts -> Enabled with zeros",
|
||||||
|
response = createResponse(
|
||||||
|
status = "enabled",
|
||||||
|
displayMode = "full",
|
||||||
|
confirmedAmount = null,
|
||||||
|
pendingAmount = null,
|
||||||
|
),
|
||||||
|
expected = CashbackSummary.Enabled(
|
||||||
|
displayMode = CashbackDisplayMode.FULL,
|
||||||
|
cashback = expectedCashback(confirmedAmount = BigDecimal.ZERO),
|
||||||
|
pendingAmount = BigDecimal.ZERO,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "enabled but missing period -> Unknown",
|
||||||
|
response = createResponse(status = "enabled", period = null),
|
||||||
|
expected = CashbackSummary.Unknown,
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "deactivated -> Deactivated",
|
||||||
|
response = createResponse(status = "deactivated"),
|
||||||
|
expected = CashbackSummary.Deactivated,
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "disabled -> Disabled",
|
||||||
|
response = createResponse(status = "disabled"),
|
||||||
|
expected = CashbackSummary.Disabled,
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "unavailable -> Disabled",
|
||||||
|
response = createResponse(status = "unavailable"),
|
||||||
|
expected = CashbackSummary.Disabled,
|
||||||
|
),
|
||||||
|
ConvertModel(
|
||||||
|
name = "unrecognized status -> Unknown",
|
||||||
|
response = createResponse(status = "something_new"),
|
||||||
|
expected = CashbackSummary.Unknown,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
internal data class ConvertModel(
|
||||||
|
val name: String,
|
||||||
|
val response: CashbackSummaryResponse,
|
||||||
|
val expected: CashbackSummary,
|
||||||
|
) {
|
||||||
|
override fun toString(): String = name
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
|
||||||
|
fun createResponse(
|
||||||
|
status: String = "enabled",
|
||||||
|
displayMode: String? = "full",
|
||||||
|
period: CashbackSummaryResponse.Period? = CashbackSummaryResponse.Period(
|
||||||
|
year = 2026,
|
||||||
|
month = 6,
|
||||||
|
payoutStartDate = "2026-07-02",
|
||||||
|
payoutEndDate = "2026-07-05",
|
||||||
|
),
|
||||||
|
confirmedAmount: BigDecimal? = BigDecimal("22.54"),
|
||||||
|
pendingAmount: BigDecimal? = BigDecimal("13.65"),
|
||||||
|
currency: String? = "USD",
|
||||||
|
) = CashbackSummaryResponse(
|
||||||
|
cashbackProgramStatus = status,
|
||||||
|
cashbackDisplayMode = displayMode,
|
||||||
|
period = period,
|
||||||
|
confirmedAmount = confirmedAmount,
|
||||||
|
pendingAmount = pendingAmount,
|
||||||
|
currency = currency,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun expectedCashback(confirmedAmount: BigDecimal = BigDecimal("22.54")) = TangemPayCashback(
|
||||||
|
confirmedAmount = confirmedAmount,
|
||||||
|
currency = "USD",
|
||||||
|
period = TangemPayCashback.Period(
|
||||||
|
year = 2026,
|
||||||
|
month = 6,
|
||||||
|
payoutStart = DateTime.parse("2026-07-02"),
|
||||||
|
payoutEnd = DateTime.parse("2026-07-05"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.tangem.domain.pay.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashback block layout variant, from `cashback_display_mode`. Present only when the program is enabled.
|
||||||
|
*
|
||||||
|
* Absent or unrecognized values fall back to [FULL] (see summary display-mode logic).
|
||||||
|
*/
|
||||||
|
enum class CashbackDisplayMode {
|
||||||
|
|
||||||
|
/** Standard cashback block. */
|
||||||
|
FULL,
|
||||||
|
|
||||||
|
/** Alternative EU/EEA block. */
|
||||||
|
ALT_BLOCK,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String?): CashbackDisplayMode = when (value?.lowercase()) {
|
||||||
|
"alt_block" -> ALT_BLOCK
|
||||||
|
else -> FULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.tangem.domain.pay.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashback program availability for the customer, from `cashback_program_status`
|
||||||
|
* in `GET /v1/customer/cashback/summary`.
|
||||||
|
*
|
||||||
|
* Unknown wire values resolve to [UNKNOWN].
|
||||||
|
*/
|
||||||
|
enum class CashbackProgramStatus {
|
||||||
|
|
||||||
|
/** Cashback is active. */
|
||||||
|
ENABLED,
|
||||||
|
|
||||||
|
/** Customer blocked due to fraud behavior; client shows the "Cashback deactivated" banner. */
|
||||||
|
DEACTIVATED,
|
||||||
|
|
||||||
|
/** Cashback not available for this cohort/region; client silently hides all cashback UI. */
|
||||||
|
DISABLED,
|
||||||
|
|
||||||
|
/** Unrecognized status. */
|
||||||
|
UNKNOWN,
|
||||||
|
;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String?): CashbackProgramStatus = when (value?.lowercase()) {
|
||||||
|
"enabled" -> ENABLED
|
||||||
|
"deactivated" -> DEACTIVATED
|
||||||
|
"disabled", "unavailable" -> DISABLED
|
||||||
|
else -> UNKNOWN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.tangem.domain.pay.model
|
||||||
|
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customer cashback summary from `GET /v1/customer/cashback/summary`.
|
||||||
|
*
|
||||||
|
* Drives the cashback widget on the Payment account screen and the Cashback screen header.
|
||||||
|
*/
|
||||||
|
sealed interface CashbackSummary {
|
||||||
|
|
||||||
|
/** Cashback is active for the customer. */
|
||||||
|
data class Enabled(
|
||||||
|
val displayMode: CashbackDisplayMode,
|
||||||
|
val cashback: TangemPayCashback,
|
||||||
|
val pendingAmount: BigDecimal,
|
||||||
|
) : CashbackSummary
|
||||||
|
|
||||||
|
/** Customer blocked due to fraud; client shows the "Cashback deactivated" banner. */
|
||||||
|
data object Deactivated : CashbackSummary
|
||||||
|
|
||||||
|
/** Cashback not available for this cohort/region; client hides all cashback UI. */
|
||||||
|
data object Disabled : CashbackSummary
|
||||||
|
|
||||||
|
/** Unrecognized program status; treated as no cashback UI. */
|
||||||
|
data object Unknown : CashbackSummary
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.tangem.domain.pay.repository
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository for the cashback endpoints (`GET /v1/customer/cashback/...`).
|
||||||
|
*/
|
||||||
|
interface CashbackRepository {
|
||||||
|
|
||||||
|
/** Loads the cashback summary for the customer of [userWalletId]. */
|
||||||
|
suspend fun getCashbackSummary(userWalletId: UserWalletId): Either<VisaApiError, CashbackSummary>
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.tangem.domain.pay.usecase
|
||||||
|
|
||||||
|
import arrow.core.Either
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.domain.pay.model.CashbackSummary
|
||||||
|
import com.tangem.domain.pay.repository.CashbackRepository
|
||||||
|
import com.tangem.domain.visa.error.VisaApiError
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the cashback summary from `GET /v1/customer/cashback/summary`.
|
||||||
|
*
|
||||||
|
* Used by the Payment account cashback widget and the Cashback screen header.
|
||||||
|
*/
|
||||||
|
class GetCashbackSummaryUseCase(
|
||||||
|
private val cashbackRepository: CashbackRepository,
|
||||||
|
) {
|
||||||
|
suspend operator fun invoke(userWalletId: UserWalletId): Either<VisaApiError, CashbackSummary> {
|
||||||
|
return cashbackRepository.getCashbackSummary(userWalletId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,5 @@ interface TangemPayFeatureToggles {
|
||||||
val isRemoveAccountEnabled: Boolean
|
val isRemoveAccountEnabled: Boolean
|
||||||
val isMultipleCardsEnabled: Boolean
|
val isMultipleCardsEnabled: Boolean
|
||||||
val isTiersPlusPlanEnabled: Boolean
|
val isTiersPlusPlanEnabled: Boolean
|
||||||
|
val isCashbackEnabled: Boolean
|
||||||
}
|
}
|
||||||
|
|
@ -21,4 +21,7 @@ internal class DefaultTangemPayFeatureToggles(
|
||||||
|
|
||||||
override val isTiersPlusPlanEnabled: Boolean
|
override val isTiersPlusPlanEnabled: Boolean
|
||||||
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.AND_16041_VISA_TIERS_PLUS_PLAN)
|
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.AND_16041_VISA_TIERS_PLUS_PLAN)
|
||||||
|
|
||||||
|
override val isCashbackEnabled: Boolean
|
||||||
|
get() = featureTogglesManager.isFeatureEnabled(FeatureToggles.TWI_1192_TANGEM_PAY_CASHBACK_ENABLED)
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue