NTP-68061 | add os check on PPS and lite mandate execution (#16337)

This commit is contained in:
Shaurya Rehan
2025-05-29 16:30:41 +05:30
committed by GitHub
parent 5b6c184d59
commit 7666988b8f
8 changed files with 51 additions and 26 deletions

View File

@@ -12,6 +12,4 @@ import com.google.gson.annotations.SerializedName
data class UpiLiteActiveAccountInfo(
@SerializedName("balance") val balance: String = "",
@SerializedName("buid") val buid: String? = "",
@SerializedName("isLiteActiveOnIos") val isLiteActiveOnIos: Boolean = false,
@SerializedName("isClBound") val isClBound: Boolean = false,
)

View File

@@ -830,7 +830,6 @@ constructor(
UpiLiteActiveAccountInfo(
buid = buid,
balance = balance.getFormattedAmountWithDecimal(),
isClBound = true,
)
),
version = 1,

View File

@@ -53,6 +53,7 @@ import javax.inject.Inject
import kotlin.math.min
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
class SubsequentLiteMandateExecutionUseCase
@@ -66,6 +67,7 @@ constructor(
private val mandateRepository: MandateRepository,
private val upiLiteClHelper: UpiLiteClHelper,
private val liteAccountSyncUseCase: LiteAccountSyncUseCase,
private val linkedAccountsUseCase: LinkedAccountsUseCase,
private val orderIdHelper: OrderIdHelper,
private val orderDetailsRepository: OrderDetailsRepository,
@NaviPayGsonBuilder private val gson: Gson,
@@ -108,7 +110,18 @@ constructor(
return
}
// Iff mandateStatus is Active, proceed, else return
// Check if active lite account is present on Android
val isActiveLiteAccountPresent =
linkedAccountsUseCase.execute().first().firstOrNull { it.hasActiveLiteAccount }
if (isActiveLiteAccountPresent == null) {
naviPayAnalytics.onDevGenericEvent(
event = "SubsequentLiteMandateExecutionUseCase_NoActiveLiteAccount"
)
return
}
// Iff mandateStatus is Active proceed, else return
if (upiLiteMandateInfo.status != MandateStatus.ACTIVE.name) {
return
}

View File

@@ -37,6 +37,7 @@ import com.navi.pay.common.model.view.UpiLiteActiveAccountInfo
import com.navi.pay.common.repository.CommonRepository
import com.navi.pay.common.repository.SharedPreferenceRepository
import com.navi.pay.common.theme.color.NaviPayColor
import com.navi.pay.common.usecase.LinkedAccountsUseCase
import com.navi.pay.common.usecase.NaviPayConfigUseCase
import com.navi.pay.common.usecase.RefreshGenericOffersUseCase
import com.navi.pay.common.utils.NaviPayCommonUtils
@@ -101,6 +102,7 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -130,6 +132,7 @@ constructor(
private val resourceProvider: ResourceProvider,
private val geoNetworkSignatureUseCase: GeoNetworkSignatureUseCase,
private val litmusExperimentsUseCase: LitmusExperimentsUseCase,
private val linkedAccountsUseCase: LinkedAccountsUseCase,
@NaviPayGsonBuilder private val gson: Gson,
) : NaviPayBaseVM() {
@@ -485,10 +488,24 @@ constructor(
}
}
private fun updateUpiLiteInfoBannerData(isAutoTopUpEnabled: Boolean, upiLiteBalance: String?) {
private suspend fun updateUpiLiteInfoBannerData(
isAutoTopUpEnabled: Boolean,
upiLiteBalance: String?,
) {
if (!FirebaseRemoteConfigHelper.getBoolean(NAVI_PAY_PPS_UPI_LITE_BANNER_ENABLED_FLAG)) {
return
}
val hasNonDeregisteredLiteAccountOnIos =
linkedAccountsUseCase.execute().first().firstOrNull {
it.hasNonDeregisteredLiteAccountOnIos
}
if (hasNonDeregisteredLiteAccountOnIos == null) {
_upiLiteInfoBannerData.update { null }
return
}
if (upiLiteBalance == null) {
_upiLiteInfoBannerData.update {
UpiLiteInfoBannerData(

View File

@@ -215,7 +215,6 @@ constructor(
UpiLiteActiveAccountInfo(
buid = buid,
balance = balance.getFormattedAmountWithDecimal(),
isClBound = true,
)
),
version = 1,

View File

@@ -27,7 +27,6 @@ import com.navi.common.network.models.RepoResult
import com.navi.common.network.models.isSuccessWithData
import com.navi.common.utils.CommonUtils.getDisplayableAmount
import com.navi.common.utils.CommonUtils.isAmountValid
import com.navi.common.utils.Constants
import com.navi.common.utils.Constants.OS_ANDROID
import com.navi.common.utils.NaviApiPoller
import com.navi.common.utils.log
@@ -1530,13 +1529,9 @@ constructor(
}
private fun isLiteAccountActiveOnIos(): Boolean =
linkedAccounts.value
.any { linkedAccountEntity ->
linkedAccountEntity.upiLiteInfo.any {
shouldBlockIOSLiteCustomer(upiLiteEntity = it)
}
}
.orFalse() || activeLiteAccountInfoFromCache.isLiteActiveOnIos
linkedAccounts.value.any { linkedAccountEntity ->
linkedAccountEntity.hasNonDeregisteredLiteAccountOnIos
}
private suspend fun isLiteActiveOnIos(): Boolean {
val isActive = isLiteAccountActiveOnIos()
@@ -1578,15 +1573,6 @@ constructor(
}
}
private fun shouldBlockIOSLiteCustomer(upiLiteEntity: UPILiteEntity) =
(upiLiteEntity.accountStatus == UPILiteAccountStatus.ACTIVE &&
upiLiteEntity.os == Constants.OS_IOS) ||
(upiLiteEntity.accountStatus == UPILiteAccountStatus.PENDING_ACTIVATION &&
upiLiteEntity.initialTopUpStatus.isPendingState() &&
upiLiteEntity.os == Constants.OS_IOS) ||
(upiLiteEntity.accountStatus == UPILiteAccountStatus.PENDING_DEREGISTRATION &&
upiLiteEntity.os == Constants.OS_IOS)
fun enteredAmountInputChanged(
newInput: String,
isAmountChangedByChipSelection: Boolean = false,
@@ -2437,8 +2423,6 @@ constructor(
UpiLiteActiveAccountInfo(
buid = buid,
balance = balance.getFormattedAmountWithDecimal(),
isClBound = true,
isLiteActiveOnIos = false,
)
),
version = 1,

View File

@@ -362,7 +362,7 @@ fun RenderModifyMandateScreen(
placeholder = {
NaviText(
modifier = Modifier.wrapContentWidth(),
text = stringResource(id = R.string.np_enter_amount),
text = stringResource(id = R.string.np_enter_amount_without_rupee),
fontSize = 18.sp,
fontFamily = naviFontFamily,
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),

View File

@@ -10,6 +10,7 @@ package com.navi.pay.onboarding.account.detail.model.view
import android.os.Parcelable
import androidx.annotation.DrawableRes
import androidx.room.Ignore
import com.navi.common.utils.Constants
import com.navi.common.utils.Constants.OS_ANDROID
import com.navi.pay.common.bankuptime.model.view.BankUptimeEntity
import com.navi.pay.common.model.view.PspType
@@ -17,6 +18,7 @@ import com.navi.pay.common.utils.getBankNameAccountNumberText
import com.navi.pay.common.utils.getBankNameTruncatedAccountNumberText
import com.navi.pay.common.utils.getMaskedAccountNumberWithHyphen
import com.navi.pay.management.common.sendmoney.model.view.EligibilityState
import com.navi.pay.management.lite.models.view.InitialTopUpStatus.Companion.isPendingState
import com.navi.pay.management.lite.models.view.UPILiteAccountStatus
import com.navi.pay.management.lite.models.view.UPILiteEntity
import com.navi.pay.onboarding.account.common.model.view.UpiGlobalInfoEntity
@@ -85,6 +87,19 @@ data class LinkedAccountEntity(
}
}
@delegate:Ignore
@IgnoredOnParcel
val hasNonDeregisteredLiteAccountOnIos by lazy {
upiLiteInfo.any {
(it.accountStatus == UPILiteAccountStatus.ACTIVE && it.os == Constants.OS_IOS) ||
(it.accountStatus == UPILiteAccountStatus.PENDING_ACTIVATION &&
it.initialTopUpStatus.isPendingState() &&
it.os == Constants.OS_IOS) ||
(it.accountStatus == UPILiteAccountStatus.PENDING_DEREGISTRATION &&
it.os == Constants.OS_IOS)
}
}
@delegate:Ignore
@IgnoredOnParcel
val nonDeregisteredLiteAccountLrn by lazy {