NTP-14219 | PS | Net Banking list based on vertical and category (#14165)
This commit is contained in:
@@ -21,6 +21,8 @@ import com.navi.base.utils.SUCCESS
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.common.model.UploadDataAsyncResponse
|
||||
import com.navi.common.utils.isValidResponse
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.utils.PaymentSource
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -28,7 +30,10 @@ import kotlinx.coroutines.launch
|
||||
@HiltViewModel
|
||||
class PennyDropOptionsViewModel
|
||||
@Inject
|
||||
constructor(private val repository: PennyDropOptionsRepository) : BaseAmcVM() {
|
||||
constructor(
|
||||
private val repository: PennyDropOptionsRepository,
|
||||
private val pmsNetBankingUseCase: NetBankingUseCase
|
||||
) : BaseAmcVM() {
|
||||
|
||||
var requestId: String? = null
|
||||
|
||||
@@ -84,6 +89,7 @@ constructor(private val repository: PennyDropOptionsRepository) : BaseAmcVM() {
|
||||
} else {
|
||||
setErrorData(response.errors, response.error)
|
||||
}
|
||||
pmsNetBankingUseCase.clearBankListForVertical(PaymentSource.AMC.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,13 +17,19 @@ import com.navi.amc.kyc.model.BankDetailsResponse
|
||||
import com.navi.amc.kyc.repository.BankDetailsRepository
|
||||
import com.navi.common.network.models.SuccessResponse
|
||||
import com.navi.common.utils.Constants.AMC_KYC_BANK_DETAILS_URL
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.utils.PaymentSource
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@HiltViewModel
|
||||
class BankDetailsVM @Inject constructor(private val repository: BankDetailsRepository) :
|
||||
BaseAmcVM() {
|
||||
class BankDetailsVM
|
||||
@Inject
|
||||
constructor(
|
||||
private val repository: BankDetailsRepository,
|
||||
private val pmsNetBankingUseCase: NetBankingUseCase
|
||||
) : BaseAmcVM() {
|
||||
|
||||
private val _bankItems = MutableLiveData<BankDetailsResponse?>()
|
||||
val bankItems: LiveData<BankDetailsResponse?>
|
||||
@@ -71,6 +77,7 @@ class BankDetailsVM @Inject constructor(private val repository: BankDetailsRepos
|
||||
} else {
|
||||
setErrorData(response.errors, response.error)
|
||||
}
|
||||
pmsNetBankingUseCase.clearBankListForVertical(PaymentSource.AMC.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@ object FirebaseRemoteConfigHelper {
|
||||
const val NAVI_PMT_DISABLE_WEB_PAYMENTS = "NAVI_PMT_DISABLE_WEB_PAYMENTS"
|
||||
const val NAVI_PMT_RETRY_POLICY_ENABLED = "NAVI_PMT_RETRY_POLICY_ENABLED"
|
||||
const val NAVI_PMT_API_CONNECT_TIMEOUT = "NAVI_PMT_API_CONNECT_TIMEOUT"
|
||||
const val NAVI_PMT_NET_BANKING_CACHE_TTL = "NAVI_PMT_NET_BANKING_CACHE_TTL"
|
||||
|
||||
// BBPS
|
||||
const val NAVI_BBPS_REWARDS_NUDGE_CACHE_TTL_IN_MILLIS =
|
||||
|
||||
@@ -17,6 +17,7 @@ import kotlinx.parcelize.RawValue
|
||||
data class PaymentPrefetchMethodRequest(
|
||||
@SerializedName("prefetchDetails") var prefetchDetails: List<PaymentPrefetchDetail>? = null,
|
||||
@SerializedName("previousScreenName") val previousScreenName: String? = null,
|
||||
@SerializedName("shouldFetchBankList") val shouldFetchBankList: Boolean = false,
|
||||
@SerializedName("additionalParam")
|
||||
var additionalParam: AdditionalParam? = AdditionalParam("CLIENT_PAYNOW"),
|
||||
@SerializedName("callSdkExitOnBack") var callSdkExitOnBack: Boolean = true
|
||||
|
||||
@@ -30,6 +30,7 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.common.utils.EMPTY
|
||||
import com.navi.common.utils.clickableDebounce
|
||||
import com.navi.design.font.FontWeightEnum
|
||||
@@ -42,7 +43,7 @@ import com.navi.pay.common.theme.color.NaviPayColor.inputFieldFilled
|
||||
import com.navi.pay.common.ui.ImageWithCircularBackground
|
||||
import com.navi.pay.utils.getMaskedAccountNumber
|
||||
import com.navi.payment.R
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NPSScreenContract
|
||||
|
||||
@Composable
|
||||
@@ -50,8 +51,8 @@ fun NPSNetBankingWidget(
|
||||
paymentOptionIconUrl: String,
|
||||
onAction: (action: NPSScreenContract.NPSScreenEvent) -> Unit,
|
||||
requireRedirection: Boolean,
|
||||
bankDetailsList: List<BankDetails>,
|
||||
selectedBankDetails: BankDetails?
|
||||
banksList: List<BankEntity>,
|
||||
selectedBank: BankEntity?
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
NpsPaymentInstrumentHeader(header = stringResource(id = R.string.net_banking_card_header))
|
||||
@@ -65,8 +66,8 @@ fun NPSNetBankingWidget(
|
||||
)
|
||||
} else {
|
||||
NpsNetbankingList(
|
||||
bankDetailsList = bankDetailsList,
|
||||
selectedBankDetails = selectedBankDetails,
|
||||
banksList = banksList,
|
||||
selectedBank = selectedBank,
|
||||
onClick = { bankDetail ->
|
||||
onAction(NPSScreenContract.NPSScreenEvent.OnNetbankingBankSelected(bankDetail))
|
||||
}
|
||||
@@ -77,15 +78,15 @@ fun NPSNetBankingWidget(
|
||||
|
||||
@Composable
|
||||
fun NpsNetbankingList(
|
||||
bankDetailsList: List<BankDetails>,
|
||||
onClick: (bankDetail: BankDetails) -> Unit,
|
||||
selectedBankDetails: BankDetails?
|
||||
banksList: List<BankEntity>,
|
||||
onClick: (bankEntity: BankEntity) -> Unit,
|
||||
selectedBank: BankEntity?
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 16.dp)) {
|
||||
bankDetailsList.forEach { bankDetail ->
|
||||
banksList.forEach { bankDetail ->
|
||||
NpsNetbankingBankItem(
|
||||
bankDetail = bankDetail,
|
||||
isSelected = selectedBankDetails == bankDetail,
|
||||
bankEntity = bankDetail,
|
||||
isSelected = selectedBank == bankDetail,
|
||||
onClick = onClick
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
@@ -95,9 +96,9 @@ fun NpsNetbankingList(
|
||||
|
||||
@Composable
|
||||
fun NpsNetbankingBankItem(
|
||||
bankDetail: BankDetails,
|
||||
bankEntity: BankEntity,
|
||||
isSelected: Boolean,
|
||||
onClick: (bankDetail: BankDetails) -> Unit
|
||||
onClick: (bankEntity: BankEntity) -> Unit
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@@ -114,19 +115,19 @@ fun NpsNetbankingBankItem(
|
||||
border = BorderStroke(width = 1.dp, color = NaviPayColor.borderDefault),
|
||||
shape = RoundedCornerShape(4.dp)
|
||||
)
|
||||
.clickableDebounce { onClick.invoke(bankDetail) }
|
||||
.clickableDebounce { onClick.invoke(bankEntity) }
|
||||
.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.weight(1f)) {
|
||||
ImageWithCircularBackground(
|
||||
boxSize = 40.dp,
|
||||
imageUrl = bankDetail.bankIcon,
|
||||
imageUrl = bankEntity.iconUrl,
|
||||
imageSize = 24.dp
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
NaviText(
|
||||
modifier = Modifier.weight(1f, fill = false),
|
||||
text = bankDetail.bankTitle,
|
||||
text = bankEntity.name,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
fontFamily = naviFontFamily,
|
||||
@@ -135,9 +136,9 @@ fun NpsNetbankingBankItem(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
)
|
||||
if (bankDetail.bankAccountNumber.isNotEmpty()) {
|
||||
if (bankEntity.accountNumber.isNotNullAndNotEmpty()) {
|
||||
NaviText(
|
||||
text = " - ${bankDetail.bankAccountNumber.getMaskedAccountNumber()}",
|
||||
text = " - ${bankEntity.accountNumber?.getMaskedAccountNumber()}",
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
fontFamily = naviFontFamily,
|
||||
|
||||
@@ -63,17 +63,17 @@ import com.navi.pay.common.ui.ImageWithCircularBackground
|
||||
import com.navi.pay.utils.NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE
|
||||
import com.navi.payment.R
|
||||
import com.navi.payment.nativepayment.common.theme.NaviPmsColor
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
|
||||
@Composable
|
||||
fun NetBankingScreenListSection(
|
||||
showPopularBanks: Boolean,
|
||||
popularBanks: List<BankDetails>,
|
||||
allBanks: List<BankDetails>,
|
||||
onBankSelected: (bankDetails: BankDetails, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankDetails?,
|
||||
popularBanks: List<BankEntity>,
|
||||
allBanks: List<BankEntity>,
|
||||
onBankSelected: (bankEntity: BankEntity, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankEntity?,
|
||||
isSelectedFromPopularBanks: Boolean
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
@@ -154,9 +154,9 @@ fun NetBankingScreenListSection(
|
||||
|
||||
@Composable
|
||||
fun PopularBanksListSection(
|
||||
popularBanks: List<BankDetails>,
|
||||
onBankSelected: (bankDetails: BankDetails, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankDetails?,
|
||||
popularBanks: List<BankEntity>,
|
||||
onBankSelected: (bankEntity: BankEntity, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankEntity?,
|
||||
isSelectedFromPopularBanks: Boolean
|
||||
) {
|
||||
Column {
|
||||
@@ -182,7 +182,7 @@ fun PopularBanksListSection(
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
items(items = popularBanks, key = { it.bankCode }) { bankEntity ->
|
||||
items(items = popularBanks, key = { it.code }) { bankEntity ->
|
||||
PopularBanksGridItem(
|
||||
bankEntity = bankEntity,
|
||||
height = 100.dp,
|
||||
@@ -197,10 +197,10 @@ fun PopularBanksListSection(
|
||||
|
||||
@Composable
|
||||
fun PopularBanksGridItem(
|
||||
bankEntity: BankDetails,
|
||||
bankEntity: BankEntity,
|
||||
height: Dp = 100.dp,
|
||||
onBankSelected: (bankDetails: BankDetails, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankDetails?,
|
||||
onBankSelected: (bankEntity: BankEntity, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankEntity?,
|
||||
isSelectedFromPopularBanks: Boolean
|
||||
) {
|
||||
Card(
|
||||
@@ -221,16 +221,16 @@ fun PopularBanksGridItem(
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
ImageWithCircularBackground(
|
||||
imageUrl = bankEntity.bankIcon,
|
||||
imageUrl = bankEntity.iconUrl,
|
||||
boxSize = 40.dp,
|
||||
imageSize = 28.dp
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
if (selectedBank?.bankCode == bankEntity.bankCode && isSelectedFromPopularBanks) {
|
||||
if (selectedBank?.code == bankEntity.code && isSelectedFromPopularBanks) {
|
||||
ButtonLoaderLottie()
|
||||
} else {
|
||||
NaviText(
|
||||
text = bankEntity.bankTitle,
|
||||
text = bankEntity.name,
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 18.sp,
|
||||
fontFamily = naviFontFamily,
|
||||
@@ -248,9 +248,9 @@ fun PopularBanksGridItem(
|
||||
|
||||
@Composable
|
||||
fun RegularBanksListItem(
|
||||
bankEntity: BankDetails,
|
||||
onBankSelected: (bankDetails: BankDetails, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankDetails?,
|
||||
bankEntity: BankEntity,
|
||||
onBankSelected: (bankEntity: BankEntity, isPopularBank: Boolean) -> Unit,
|
||||
selectedBank: BankEntity?,
|
||||
isSelectedFromPopularBanks: Boolean
|
||||
) {
|
||||
Row(
|
||||
@@ -261,7 +261,7 @@ fun RegularBanksListItem(
|
||||
.padding(top = 8.dp, bottom = 8.dp)
|
||||
) {
|
||||
ImageWithCircularBackground(
|
||||
imageUrl = bankEntity.bankIcon,
|
||||
imageUrl = bankEntity.iconUrl,
|
||||
backgroundColor = NaviPayColor.bgDefault,
|
||||
fallbackIconUrl = CommonR.drawable.ic_upi_bbps_default_bank_logo,
|
||||
boxSize = 40.dp,
|
||||
@@ -273,7 +273,7 @@ fun RegularBanksListItem(
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
|
||||
NaviText(
|
||||
text = bankEntity.bankTitle,
|
||||
text = bankEntity.name,
|
||||
fontSize = 14.sp,
|
||||
lineHeight = 22.sp,
|
||||
fontFamily = naviFontFamily,
|
||||
@@ -283,7 +283,7 @@ fun RegularBanksListItem(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
if (selectedBank?.bankCode == bankEntity.bankCode && !isSelectedFromPopularBanks) {
|
||||
if (selectedBank?.code == bankEntity.code && !isSelectedFromPopularBanks) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
ButtonLoaderLottie()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
package com.navi.payment.nativepayment.dataprovider
|
||||
|
||||
import com.navi.common.utils.SoftRefLruCache
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.model.BasePaymentMethodResponse
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
@@ -26,9 +25,6 @@ class PaymentDataProvider @Inject constructor() {
|
||||
private val _paymentMethodResponse = MutableStateFlow<BasePaymentMethodResponse?>(null)
|
||||
val paymentMethodResponse = _paymentMethodResponse.asStateFlow()
|
||||
|
||||
private val _netBankingBankDetails = MutableStateFlow<List<BankDetails>>(value = emptyList())
|
||||
val netBankingBankDetails = _netBankingBankDetails.asStateFlow()
|
||||
|
||||
private val _isDiscountPreApplied = MutableStateFlow(false)
|
||||
val isDiscountPreApplied = _isDiscountPreApplied.asStateFlow()
|
||||
|
||||
@@ -60,7 +56,6 @@ class PaymentDataProvider @Inject constructor() {
|
||||
analyticsEventParams.clear()
|
||||
sourceEventProperties.clear()
|
||||
_paymentMethodResponse.update { null }
|
||||
_netBankingBankDetails.update { emptyList() }
|
||||
_isDiscountPreApplied.update { false }
|
||||
}
|
||||
|
||||
@@ -91,10 +86,6 @@ class PaymentDataProvider @Inject constructor() {
|
||||
_isDiscountPreApplied.update { isDiscountApplied }
|
||||
}
|
||||
|
||||
fun updateNetBankingBanksResponse(banks: List<BankDetails>) {
|
||||
_netBankingBankDetails.update { banks }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_CONSUMPTION_LIMIT = 100
|
||||
private const val MAX_TTL = 60 * 60 * 1000L
|
||||
|
||||
@@ -9,16 +9,45 @@ package com.navi.payment.nativepayment.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.payment.nativepayment.db.converter.BanksEntityConverter
|
||||
import com.navi.payment.nativepayment.db.dao.BankListDao
|
||||
import com.navi.payment.nativepayment.db.dao.TransactionStatusRequestDao
|
||||
import com.navi.payment.nativepayment.db.model.BankListEntity
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
|
||||
@Database(entities = [TransactionStatusRequestEntity::class], version = 1, exportSchema = false)
|
||||
@Database(
|
||||
entities = [TransactionStatusRequestEntity::class, BankListEntity::class],
|
||||
version = 2,
|
||||
exportSchema = false
|
||||
)
|
||||
@TypeConverters(BanksEntityConverter::class)
|
||||
abstract class NaviPaymentAppDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun transactionStatusRequestDao(): TransactionStatusRequestDao
|
||||
|
||||
abstract fun bankListDao(): BankListDao
|
||||
|
||||
companion object {
|
||||
const val NAVI_PAYMENT_DATABASE_NAME = "navi-payment.db"
|
||||
const val TRANSACTION_STATUS_REQUEST_TABLE = "transaction_status_request"
|
||||
const val BANKS_TABLE = "banks"
|
||||
}
|
||||
}
|
||||
|
||||
val NAVI_PAYMENT_APP_DATABASE_MIGRATION_1_2 =
|
||||
object : Migration(1, 2) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
database.execSQL(
|
||||
"CREATE TABLE IF NOT EXISTS ${NaviPaymentAppDatabase.BANKS_TABLE} (" +
|
||||
"`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
|
||||
"`vertical` TEXT NOT NULL, " +
|
||||
"`category` TEXT NOT NULL DEFAULT '${DEFAULT}', " +
|
||||
"`bankList` TEXT NOT NULL, " +
|
||||
"`updatedAt` INTEGER NOT NULL)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.converter
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
|
||||
class BanksEntityConverter {
|
||||
private val gson = Gson()
|
||||
|
||||
@TypeConverter
|
||||
fun fromBankEntityList(bankEntityList: List<BankEntity>): String {
|
||||
return gson.toJson(bankEntityList)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun toPlansEntityList(bankEntityListString: String): List<BankEntity> {
|
||||
val type = object : TypeToken<List<BankEntity>>() {}.type
|
||||
return gson.fromJson(bankEntityListString, type)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase
|
||||
import com.navi.payment.nativepayment.db.model.BankListEntity
|
||||
|
||||
@Dao
|
||||
interface BankListDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(bankListEntity: BankListEntity)
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM ${NaviPaymentAppDatabase.BANKS_TABLE} WHERE vertical = :vertical AND category = :category LIMIT 1"
|
||||
)
|
||||
suspend fun getBanksForVerticalAndCategory(vertical: String, category: String): BankListEntity?
|
||||
|
||||
@Query("DELETE FROM ${NaviPaymentAppDatabase.BANKS_TABLE} WHERE vertical = :vertical")
|
||||
suspend fun deleteBanksForVertical(vertical: String)
|
||||
|
||||
@Query(
|
||||
"DELETE FROM ${NaviPaymentAppDatabase.BANKS_TABLE} WHERE vertical = :vertical AND category = :category"
|
||||
)
|
||||
suspend fun deleteBanksForVerticalAndCategory(vertical: String, category: String)
|
||||
|
||||
@Query("DELETE FROM ${NaviPaymentAppDatabase.BANKS_TABLE}") suspend fun deleteAll()
|
||||
}
|
||||
@@ -9,6 +9,7 @@ package com.navi.payment.nativepayment.db.di
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.navi.payment.nativepayment.db.NAVI_PAYMENT_APP_DATABASE_MIGRATION_1_2
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase.Companion.NAVI_PAYMENT_DATABASE_NAME
|
||||
import dagger.Module
|
||||
@@ -30,10 +31,17 @@ object NaviPaymentDbModule {
|
||||
NaviPaymentAppDatabase::class.java,
|
||||
NAVI_PAYMENT_DATABASE_NAME
|
||||
)
|
||||
.addMigrations(NAVI_PAYMENT_APP_DATABASE_MIGRATION_1_2)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun providesTransactionStatusDao(naviPaymentAppDatabase: NaviPaymentAppDatabase) =
|
||||
naviPaymentAppDatabase.transactionStatusRequestDao()
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
fun providesBankListDao(naviPaymentAppDatabase: NaviPaymentAppDatabase) =
|
||||
naviPaymentAppDatabase.bankListDao()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.db.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverters
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.payment.nativepayment.db.NaviPaymentAppDatabase
|
||||
import com.navi.payment.nativepayment.db.converter.BanksEntityConverter
|
||||
|
||||
@Entity(tableName = NaviPaymentAppDatabase.BANKS_TABLE)
|
||||
data class BankListEntity(
|
||||
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") var id: Int = 0,
|
||||
@ColumnInfo(name = "vertical") val vertical: String,
|
||||
@ColumnInfo(name = "category") val category: String = DEFAULT,
|
||||
@TypeConverters(BanksEntityConverter::class)
|
||||
@ColumnInfo(name = "bankList")
|
||||
val bankList: List<BankEntity>,
|
||||
@ColumnInfo(name = "updatedAt") val updatedAt: Long
|
||||
)
|
||||
|
||||
data class BankEntity(
|
||||
@ColumnInfo(name = "code") val code: String,
|
||||
@ColumnInfo(name = "name") val name: String,
|
||||
@ColumnInfo(name = "popular") val popular: Boolean,
|
||||
@ColumnInfo(name = "iconUrl") val iconUrl: String,
|
||||
@ColumnInfo(name = "accountNumber") val accountNumber: String? = null
|
||||
)
|
||||
@@ -9,6 +9,7 @@ package com.navi.payment.nativepayment.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
|
||||
data class NetBankingPaymentInstrument(
|
||||
@SerializedName("instrumentName") override val instrumentName: String?,
|
||||
@@ -34,3 +35,13 @@ data class BankDetails(
|
||||
@SerializedName("isBankPopular") val isBankPopular: Boolean = false,
|
||||
@SerializedName("bankAccountNumber") val bankAccountNumber: String = EMPTY
|
||||
)
|
||||
|
||||
fun BankDetails.toBankEntity(): BankEntity {
|
||||
return BankEntity(
|
||||
code = bankCode,
|
||||
name = bankTitle,
|
||||
popular = isBankPopular,
|
||||
iconUrl = bankIcon,
|
||||
accountNumber = bankAccountNumber
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import com.navi.pay.management.common.sendmoney.model.view.EligibilityState
|
||||
import com.navi.pay.management.common.sendmoney.model.view.PMSSendMoneyStatus
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.utils.SAVINGS_ONLY_ENABLED_ACCOUNTS
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.nativepayment.model.CoinDetails
|
||||
import com.navi.payment.nativepayment.model.CoinRewards
|
||||
import com.navi.payment.nativepayment.model.FomoBottomSheetCtaAction
|
||||
@@ -59,13 +59,18 @@ interface NPSScreenContract : NPSBaseContract {
|
||||
|
||||
data class OnFomoSheetCtaClicked(val action: FomoBottomSheetCtaAction) : NPSScreenEvent
|
||||
|
||||
data class OnNetbankingBankSelected(val bankDetails: BankDetails) : NPSScreenEvent
|
||||
data class OnNetbankingBankSelected(val bankEntity: BankEntity) : NPSScreenEvent
|
||||
}
|
||||
|
||||
interface NPSScreenEffect : NPSBaseContract.Effect {
|
||||
data object NavigateToUpiIntentScreen : NPSScreenEffect
|
||||
|
||||
data object NavigateToNetBankingScreen : NPSScreenEffect
|
||||
data class NavigateToNetBankingScreen(
|
||||
val paymentAmount: Double,
|
||||
val token: String,
|
||||
val vertical: String,
|
||||
val category: String
|
||||
) : NPSScreenEffect
|
||||
|
||||
data class StartNaviUpiAddAccount(
|
||||
val addAccountType: String = SAVINGS_ONLY_ENABLED_ACCOUNTS
|
||||
@@ -85,7 +90,13 @@ interface NPSScreenContract : NPSBaseContract {
|
||||
|
||||
data object ScrollToTop : NPSScreenEffect
|
||||
|
||||
data class NavigateToNextScreen(val direction: String) : NPSScreenEffect
|
||||
data class NavigateToNextScreen(
|
||||
val direction: String,
|
||||
val paymentAmount: Double,
|
||||
val token: String,
|
||||
val vertical: String,
|
||||
val category: String
|
||||
) : NPSScreenEffect
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +146,6 @@ data class InstrumentIconDetails(
|
||||
|
||||
data class NetbankingDetails(
|
||||
val requireRedirection: Boolean,
|
||||
val availableBanks: List<BankDetails>,
|
||||
val selectedBank: BankDetails?
|
||||
val availableBanks: List<BankEntity>,
|
||||
val selectedBank: BankEntity?
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ package com.navi.payment.nativepayment.presentation.reducer
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import com.navi.common.basemvi.UiEvent
|
||||
import com.navi.common.basemvi.UiState
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.paymentscreen.model.PayNowResponse
|
||||
import org.json.JSONObject
|
||||
|
||||
@@ -22,18 +22,18 @@ interface NetBankingScreenContract :
|
||||
data class NetBankingScreenState(
|
||||
val searchQuery: TextFieldValue,
|
||||
val isLoading: Boolean,
|
||||
val allBanksList: List<BankDetails>?,
|
||||
val popularBanksList: List<BankDetails>?,
|
||||
val allBanksList: List<BankEntity>?,
|
||||
val popularBanksList: List<BankEntity>?,
|
||||
val showPopularBanks: Boolean,
|
||||
val paymentAmount: Double,
|
||||
val selectedBank: BankDetails?,
|
||||
val selectedBank: BankEntity?,
|
||||
val isSelectedFromPopularBanks: Boolean,
|
||||
) : UiState
|
||||
|
||||
sealed interface NetBankingScreenEvent : UiEvent {
|
||||
data class OnSearchQueryChange(val query: TextFieldValue) : NetBankingScreenEvent
|
||||
|
||||
data class OnBankSelected(val bankDetails: BankDetails, val isPopularBank: Boolean) :
|
||||
data class OnBankSelected(val bankEntity: BankEntity, val isPopularBank: Boolean) :
|
||||
NetBankingScreenEvent
|
||||
|
||||
data object OnClearSearchQueryClicked : NetBankingScreenEvent
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.repository
|
||||
|
||||
import com.navi.common.network.retrofit.ResponseCallback
|
||||
import com.navi.payment.nativepayment.db.dao.BankListDao
|
||||
import com.navi.payment.nativepayment.db.model.BankListEntity
|
||||
import javax.inject.Inject
|
||||
|
||||
class BanksRepository @Inject constructor(private val bankListDao: BankListDao) :
|
||||
ResponseCallback() {
|
||||
|
||||
suspend fun insertBanksList(bankListEntity: BankListEntity) {
|
||||
bankListDao.insert(bankListEntity)
|
||||
}
|
||||
|
||||
suspend fun getBanksList(vertical: String, category: String): BankListEntity? {
|
||||
return bankListDao.getBanksForVerticalAndCategory(vertical, category)
|
||||
}
|
||||
|
||||
suspend fun clearBanksListForVerticalAndCategory(vertical: String, category: String) {
|
||||
bankListDao.deleteBanksForVerticalAndCategory(vertical, category)
|
||||
}
|
||||
|
||||
suspend fun clearBanksListForVertical(vertical: String) {
|
||||
bankListDao.deleteBanksForVertical(vertical)
|
||||
}
|
||||
|
||||
suspend fun clearBanksList() {
|
||||
bankListDao.deleteAll()
|
||||
}
|
||||
}
|
||||
@@ -437,10 +437,8 @@ private fun NpsMainScreen(
|
||||
onAction = onEvent,
|
||||
requireRedirection =
|
||||
screenState.netBankingDetails.requireRedirection,
|
||||
bankDetailsList =
|
||||
screenState.netBankingDetails.availableBanks,
|
||||
selectedBankDetails =
|
||||
screenState.netBankingDetails.selectedBank
|
||||
banksList = screenState.netBankingDetails.availableBanks,
|
||||
selectedBank = screenState.netBankingDetails.selectedBank
|
||||
)
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
}
|
||||
@@ -825,7 +823,14 @@ private fun EffectsHandler(
|
||||
)
|
||||
}
|
||||
is NPSScreenContract.NPSScreenEffect.NavigateToNetBankingScreen -> {
|
||||
navigator.navigate(NetBankingScreenRootDestination)
|
||||
navigator.navigate(
|
||||
NetBankingScreenRootDestination(
|
||||
paymentAmount = effect.paymentAmount,
|
||||
token = effect.token,
|
||||
vertical = effect.vertical,
|
||||
category = effect.category
|
||||
)
|
||||
)
|
||||
}
|
||||
is NPSScreenContract.NPSScreenEffect.NavigateToNextScreen -> {
|
||||
when (effect.direction) {
|
||||
@@ -836,7 +841,14 @@ private fun EffectsHandler(
|
||||
navigator.navigate(CardDetailScreenRootDestination)
|
||||
}
|
||||
NaviPaymentScreenType.NET_BANKING.name -> {
|
||||
navigator.navigate(NetBankingScreenRootDestination)
|
||||
navigator.navigate(
|
||||
NetBankingScreenRootDestination(
|
||||
paymentAmount = effect.paymentAmount,
|
||||
token = effect.token,
|
||||
vertical = effect.vertical,
|
||||
category = effect.category
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
@@ -83,6 +83,10 @@ import org.json.JSONObject
|
||||
fun NetBankingScreenRoot(
|
||||
naviPaymentActivity: NaviPaymentActivity,
|
||||
navigator: DestinationsNavigator,
|
||||
paymentAmount: Double,
|
||||
token: String,
|
||||
vertical: String,
|
||||
category: String,
|
||||
netBankingViewModel: NetBankingViewModel = hiltViewModel(),
|
||||
naviPaymentAnalytics: NaviPaymentAnalytics.NetBankingScreen =
|
||||
NaviPaymentAnalytics.INSTANCE.NetBankingScreen()
|
||||
@@ -180,7 +184,7 @@ fun NetBankingScreen(
|
||||
onBankSelected = { bankDetails, isPopularBank ->
|
||||
onEvent(
|
||||
NetBankingScreenEvent.OnBankSelected(
|
||||
bankDetails = bankDetails,
|
||||
bankEntity = bankDetails,
|
||||
isPopularBank = isPopularBank
|
||||
)
|
||||
)
|
||||
|
||||
@@ -10,10 +10,12 @@ package com.navi.payment.nativepayment.sharedviewmodel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.AppServiceManager
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.common.upi.UpiDataType
|
||||
import com.navi.common.usecase.LitmusExperimentsUseCase
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.pay.common.setup.NaviPayManager
|
||||
import com.navi.payment.model.common.PaymentSdkInitParams
|
||||
import com.navi.payment.model.initiatesdk.PaymentPrefetchDetail
|
||||
@@ -27,9 +29,11 @@ import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.SCREEN_TYPE
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.SDK_PARAMS
|
||||
import com.navi.payment.nativepayment.model.NaviPaymentScreenType
|
||||
import com.navi.payment.nativepayment.model.NetBankingPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.PaymentActionType
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.nativepayment.utils.getPayloadBasedOnType
|
||||
import com.navi.payment.nativepayment.utils.toGenericErrorResponse
|
||||
import com.navi.payment.nativepayment.viewmodel.NaviPaymentBaseVM
|
||||
@@ -57,6 +61,7 @@ constructor(
|
||||
private val naviPayManager: NaviPayManager,
|
||||
private val paymentDataProvider: PaymentDataProvider,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
private val netBankingUseCase: NetBankingUseCase,
|
||||
private val litmusExperimentsUseCase: LitmusExperimentsUseCase
|
||||
) : NaviPaymentBaseVM(NaviPaymentAnalyticScreenName.CHECKOUT_SCREEN.screenName) {
|
||||
|
||||
@@ -67,7 +72,7 @@ constructor(
|
||||
paymentSdkInitParams: PaymentSdkInitParams,
|
||||
) {
|
||||
viewModelScope.safeLaunch {
|
||||
fetchPmsExperimentsData(paymentSdkInitParams?.paymentSource.orEmpty())
|
||||
fetchPmsExperimentsData(paymentSdkInitParams.paymentSource.orEmpty())
|
||||
clearPaymentData()
|
||||
paymentDataProvider.add(PAYMENT_INITIATE_START_TIME, System.currentTimeMillis())
|
||||
_paymentResponse.emit(false)
|
||||
@@ -83,6 +88,11 @@ constructor(
|
||||
) {
|
||||
connectedAccountsData?.isOnboarded = true
|
||||
}
|
||||
val isBankListAvailable =
|
||||
netBankingUseCase.isBanksListAvailable(
|
||||
paymentSdkInitParams.paymentSource.orEmpty(),
|
||||
paymentSdkInitParams.categoryId.orElse(DEFAULT)
|
||||
)
|
||||
val paymentPrefetchMethodRequest =
|
||||
PaymentPrefetchMethodRequest(
|
||||
prefetchDetails =
|
||||
@@ -93,7 +103,8 @@ constructor(
|
||||
),
|
||||
getInstalledUpiApps()
|
||||
),
|
||||
previousScreenName = paymentSdkInitParams.paymentSource
|
||||
previousScreenName = paymentSdkInitParams.paymentSource,
|
||||
shouldFetchBankList = isBankListAvailable.not()
|
||||
)
|
||||
val response =
|
||||
paymentRepository.fetchScreenData(
|
||||
@@ -106,6 +117,12 @@ constructor(
|
||||
)
|
||||
if (response.isSuccessWithData()) {
|
||||
paymentDataProvider.updatePaymentMethodResponse(response.data)
|
||||
if (isBankListAvailable.not()) {
|
||||
saveNetBankingList(
|
||||
paymentSdkInitParams = paymentSdkInitParams,
|
||||
response = response.data as? S2sPaymentMethodResponse
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val error = response.toGenericErrorResponse()
|
||||
paymentDataProvider.add(
|
||||
@@ -151,6 +168,30 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveNetBankingList(
|
||||
paymentSdkInitParams: PaymentSdkInitParams,
|
||||
response: S2sPaymentMethodResponse?
|
||||
) {
|
||||
response?.let {
|
||||
val vertical = paymentSdkInitParams.paymentSource.orEmpty()
|
||||
val category = paymentSdkInitParams.categoryId.orElse(DEFAULT)
|
||||
val bankList =
|
||||
it.methodDetails
|
||||
?.availablePaymentInstruments
|
||||
?.filterIsInstance<NetBankingPaymentInstrument>()
|
||||
?.firstOrNull()
|
||||
?.instrument
|
||||
?.availableBanks
|
||||
bankList?.let { list ->
|
||||
netBankingUseCase.insertBanksList(
|
||||
vertical = vertical,
|
||||
category = category,
|
||||
bankList = list
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearPaymentData() {
|
||||
paymentDataProvider.remove(GET_METHOD_RESPONSE)
|
||||
paymentDataProvider.remove(ERROR_RESPONSE)
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.payment.nativepayment.usecase
|
||||
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.nativepayment.db.model.BankListEntity
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.model.toBankEntity
|
||||
import com.navi.payment.nativepayment.repository.BanksRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class NetBankingUseCase
|
||||
@Inject
|
||||
constructor(
|
||||
private val banksRepository: BanksRepository,
|
||||
) {
|
||||
|
||||
suspend fun insertBanksList(
|
||||
vertical: String,
|
||||
category: String = DEFAULT,
|
||||
bankList: List<BankDetails>
|
||||
) {
|
||||
val verticalCategory = category.ifEmpty { DEFAULT }
|
||||
|
||||
val bankListEntity =
|
||||
BankListEntity(
|
||||
vertical = vertical,
|
||||
category = verticalCategory,
|
||||
bankList = bankList.map { it.toBankEntity() },
|
||||
updatedAt = System.currentTimeMillis()
|
||||
)
|
||||
|
||||
banksRepository.insertBanksList(bankListEntity)
|
||||
}
|
||||
|
||||
suspend fun isBanksListAvailable(vertical: String, category: String = DEFAULT): Boolean {
|
||||
|
||||
val verticalCategory = category.ifEmpty { DEFAULT }
|
||||
|
||||
val bankListEntity =
|
||||
banksRepository.getBanksList(vertical = vertical, category = verticalCategory)
|
||||
|
||||
val isValidBankList = isValidBankList(bankListEntity)
|
||||
|
||||
if (isValidBankList.not()) {
|
||||
banksRepository.clearBanksListForVerticalAndCategory(
|
||||
vertical = vertical,
|
||||
category = verticalCategory
|
||||
)
|
||||
}
|
||||
|
||||
return isValidBankList
|
||||
}
|
||||
|
||||
suspend fun getBanksList(vertical: String, category: String = DEFAULT): List<BankEntity>? {
|
||||
val verticalCategory = category.ifEmpty { DEFAULT }
|
||||
|
||||
val bankListEntity =
|
||||
banksRepository.getBanksList(vertical = vertical, category = verticalCategory)
|
||||
|
||||
return bankListEntity?.bankList
|
||||
}
|
||||
|
||||
suspend fun clearBankList(vertical: String, category: String = DEFAULT) {
|
||||
val verticalCategory = category.ifEmpty { DEFAULT }
|
||||
|
||||
banksRepository.clearBanksListForVerticalAndCategory(
|
||||
vertical = vertical,
|
||||
category = verticalCategory
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun clearBankListForVertical(vertical: String) {
|
||||
banksRepository.clearBanksListForVertical(vertical = vertical)
|
||||
}
|
||||
|
||||
private fun isValidBankList(bankListEntity: BankListEntity?): Boolean {
|
||||
val netBankingCachingTtl =
|
||||
FirebaseRemoteConfigHelper.getLong(
|
||||
key = FirebaseRemoteConfigHelper.NAVI_PMT_NET_BANKING_CACHE_TTL,
|
||||
defaultValue = 86400000L
|
||||
)
|
||||
|
||||
return bankListEntity?.updatedAt?.let {
|
||||
System.currentTimeMillis() - it < netBankingCachingTtl
|
||||
} ?: false
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.navi.base.utils.ResourceProvider
|
||||
import com.navi.base.utils.isNotNull
|
||||
import com.navi.base.utils.isNotNullAndNotEmpty
|
||||
import com.navi.base.utils.isNull
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.base.utils.orTrue
|
||||
import com.navi.base.utils.orZero
|
||||
@@ -31,6 +32,7 @@ import com.navi.common.upi.NAVI_PAY_RESPONSE
|
||||
import com.navi.common.upi.NaviPayAction
|
||||
import com.navi.common.upi.TYPE
|
||||
import com.navi.common.upi.UpiDataType
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.common.utils.stringToJsonObject
|
||||
import com.navi.common.utils.toJsonObject
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
@@ -54,9 +56,9 @@ import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.SCREEN_TYPE
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.getMpinSetAction
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.nativepayment.db.model.TransactionStatusRequestEntity
|
||||
import com.navi.payment.nativepayment.model.AvailableCardTypes
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.model.BasePaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.CardPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.CardPaymentInstrumentDetails
|
||||
@@ -84,6 +86,7 @@ import com.navi.payment.nativepayment.presentation.reducer.NaviUpiPaymentState
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetbankingDetails
|
||||
import com.navi.payment.nativepayment.presentation.reducer.UpiCollectOptionState
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.nativepayment.usecase.PmsLinkedAccountUseCase
|
||||
import com.navi.payment.nativepayment.utils.getDiscountAdjustedAmount
|
||||
import com.navi.payment.nativepayment.utils.getEligibilityStateForUpiLiteAccount
|
||||
@@ -137,6 +140,7 @@ class NPSViewModel
|
||||
constructor(
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val naviPayManager: NaviPayManager,
|
||||
private val netBankingUseCase: NetBankingUseCase,
|
||||
private val transactionStatusUseCase: TransactionStatusUseCase,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
resourceProvider: ResourceProvider,
|
||||
@@ -349,7 +353,7 @@ constructor(
|
||||
return updatedState
|
||||
}
|
||||
|
||||
private fun processNetBankingPaymentInstrument(
|
||||
private suspend fun processNetBankingPaymentInstrument(
|
||||
updatedState: NPSScreenContract.NPSScreenState,
|
||||
instrumentDetails: NetBankingPaymentInstumentDetails
|
||||
): NPSScreenContract.NPSScreenState {
|
||||
@@ -357,11 +361,15 @@ constructor(
|
||||
val requireRedirection = instrumentDetails.requireRedirection
|
||||
val preferredBankList =
|
||||
if (requireRedirection.not()) {
|
||||
instrumentDetails.availableBanks
|
||||
netBankingUseCase
|
||||
.getBanksList(
|
||||
vertical = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
category = paymentSdkInitParams?.categoryId.orElse(DEFAULT)
|
||||
)
|
||||
.orEmpty()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
paymentDataProvider.updateNetBankingBanksResponse(instrumentDetails.availableBanks)
|
||||
return if (iconUrl.isNotNullAndNotEmpty())
|
||||
updatedState.copy(
|
||||
iconDetails =
|
||||
@@ -604,7 +612,12 @@ constructor(
|
||||
} else {
|
||||
onDiscountApplyLottieComplete()
|
||||
_effect.emit(
|
||||
NPSScreenContract.NPSScreenEffect.NavigateToNetBankingScreen
|
||||
NPSScreenContract.NPSScreenEffect.NavigateToNetBankingScreen(
|
||||
paymentAmount = npsScreenState.npsBaseState.paymentAmount,
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
vertical = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
category = paymentSdkInitParams?.categoryId.orElse(DEFAULT)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -616,7 +629,7 @@ constructor(
|
||||
}
|
||||
is NPSScreenContract.NPSScreenEvent.OnNetbankingBankSelected -> {
|
||||
if (isInteractionAllowed) {
|
||||
handleOnNetBankingSelected(event.bankDetails)
|
||||
handleOnNetBankingSelected(event.bankEntity)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
@@ -626,11 +639,10 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleOnNetBankingSelected(bankDetails: BankDetails) {
|
||||
private suspend fun handleOnNetBankingSelected(bankEntity: BankEntity) {
|
||||
_state.update {
|
||||
npsScreenState.copy(
|
||||
netBankingDetails =
|
||||
npsScreenState.netBankingDetails.copy(selectedBank = bankDetails)
|
||||
netBankingDetails = npsScreenState.netBankingDetails.copy(selectedBank = bankEntity)
|
||||
)
|
||||
}
|
||||
handlePayNowClicked()
|
||||
@@ -664,7 +676,11 @@ constructor(
|
||||
onDiscountApplyLottieComplete()
|
||||
_effect.emit(
|
||||
NPSScreenContract.NPSScreenEffect.NavigateToNextScreen(
|
||||
fomoBottomSheetRedirection.orEmpty()
|
||||
direction = fomoBottomSheetRedirection.orEmpty(),
|
||||
paymentAmount = npsScreenState.npsBaseState.paymentAmount,
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
vertical = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
category = paymentSdkInitParams?.categoryId.orElse(DEFAULT)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -869,7 +885,7 @@ constructor(
|
||||
methodName = NetBankingPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
SelectedMethodDetails(
|
||||
bankName = npsScreenState.netBankingDetails.selectedBank?.bankCode
|
||||
bankName = npsScreenState.netBankingDetails.selectedBank?.code
|
||||
)
|
||||
)
|
||||
} else if (npsScreenState.npsBaseState.selectedUpiApp != null) {
|
||||
@@ -1028,6 +1044,12 @@ constructor(
|
||||
}
|
||||
} else {
|
||||
showLoader(false)
|
||||
_state.update {
|
||||
npsScreenState.copy(
|
||||
netBankingDetails =
|
||||
npsScreenState.netBankingDetails.copy(selectedBank = null)
|
||||
)
|
||||
}
|
||||
updateBottomSheetUIState(false)
|
||||
handleError(response = response, errorReason = PMSErrorReason.PayNowError)
|
||||
}
|
||||
|
||||
@@ -8,26 +8,26 @@
|
||||
package com.navi.payment.nativepayment.viewmodel
|
||||
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.utils.EMPTY
|
||||
import com.navi.base.utils.orElse
|
||||
import com.navi.base.utils.orZero
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.payment.model.common.PaymentSdkInitParams
|
||||
import com.navi.common.utils.Constants.DEFAULT
|
||||
import com.navi.payment.model.common.SignalPaymentData
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalyticScreenName
|
||||
import com.navi.payment.nativepayment.NaviPaymentAnalytics
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.PAYMENT_ORDER_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.dataprovider.PaymentDataProvider.Companion.TRANSACTION_REFERENCE_ID
|
||||
import com.navi.payment.nativepayment.model.BankDetails
|
||||
import com.navi.payment.nativepayment.db.model.BankEntity
|
||||
import com.navi.payment.nativepayment.model.NetBankingPaymentInstrument
|
||||
import com.navi.payment.nativepayment.model.S2sPaymentMethodResponse
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetBankingScreenContract
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetBankingScreenEffect
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetBankingScreenEvent
|
||||
import com.navi.payment.nativepayment.presentation.reducer.NetBankingScreenState
|
||||
import com.navi.payment.nativepayment.repository.PaymentRepository
|
||||
import com.navi.payment.nativepayment.usecase.NetBankingUseCase
|
||||
import com.navi.payment.network.util.PaymentsSdkRetrofit
|
||||
import com.navi.payment.paymentscreen.model.ExternalPayNowResponse
|
||||
import com.navi.payment.paymentscreen.model.PMSErrorReason
|
||||
@@ -58,8 +58,9 @@ import org.json.JSONObject
|
||||
class NetBankingViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
private val paymentDataProvider: PaymentDataProvider,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val paymentRepository: PaymentRepository,
|
||||
private val netBankingUseCase: NetBankingUseCase,
|
||||
@PaymentsSdkRetrofit private val deserializer: Gson,
|
||||
) :
|
||||
NaviPaymentBaseVM(NaviPaymentAnalyticScreenName.NET_BANKING_SCREEN.screenName),
|
||||
@@ -78,22 +79,24 @@ constructor(
|
||||
override val effect: SharedFlow<NetBankingScreenEffect>
|
||||
get() = _effect
|
||||
|
||||
private val paymentAmount = savedStateHandle.get<Double>("paymentAmount").orZero()
|
||||
private val token = savedStateHandle.get<String>("token").orEmpty()
|
||||
private val vertical = savedStateHandle.get<String>("vertical").orEmpty()
|
||||
private val category = savedStateHandle.get<String>("category").orElse(DEFAULT)
|
||||
private var payNowResponse: PayNowResponse? = null
|
||||
var paymentSdkInitParams: PaymentSdkInitParams? = null
|
||||
|
||||
private val baseAnalyticsParams = mutableMapOf<String, String>()
|
||||
private val netBankingAnalytics = NaviPaymentAnalytics.INSTANCE.NetBankingScreen()
|
||||
|
||||
private var sortedAllBanksList: List<BankDetails> = emptyList()
|
||||
private var sortedAllBanksList: List<BankEntity> = emptyList()
|
||||
|
||||
init {
|
||||
recordScreenLandTime(screenName)
|
||||
viewModelScope.safeLaunch(Dispatchers.IO) {
|
||||
paymentSdkInitParams = getSDKInitParams()
|
||||
baseAnalyticsParams.apply {
|
||||
put("token", paymentSdkInitParams?.token.orEmpty())
|
||||
put("source", paymentSdkInitParams?.paymentSource.orEmpty())
|
||||
put("category_id", paymentSdkInitParams?.categoryId.orEmpty())
|
||||
put("token", token)
|
||||
put("source", vertical)
|
||||
put("category_id", category)
|
||||
}
|
||||
fetchBanksList()
|
||||
handleOnSearchQueryChange()
|
||||
@@ -115,11 +118,11 @@ constructor(
|
||||
|
||||
private fun fetchBanksList() {
|
||||
viewModelScope.safeLaunch {
|
||||
paymentDataProvider.netBankingBankDetails.collectLatest { bankDetails ->
|
||||
if (bankDetails.isEmpty()) {
|
||||
netBankingUseCase.getBanksList(vertical, category)?.let { banksList ->
|
||||
if (banksList.isEmpty()) {
|
||||
handleEmptyBanksList()
|
||||
} else {
|
||||
handleBankDetails(bankDetails)
|
||||
handleBankDetails(banksList)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,27 +132,20 @@ constructor(
|
||||
netBankingAnalytics.emptyBanksList()
|
||||
}
|
||||
|
||||
private fun handleBankDetails(bankList: List<BankDetails>) {
|
||||
val popularBanksList = bankList.filter { it.isBankPopular }
|
||||
sortedAllBanksList = bankList.sortedBy { it.bankTitle }
|
||||
|
||||
val paymentMethodResponse =
|
||||
paymentDataProvider.paymentMethodResponse.value as? S2sPaymentMethodResponse?
|
||||
private fun handleBankDetails(bankList: List<BankEntity>) {
|
||||
val popularBanksList = bankList.filter { it.popular }
|
||||
sortedAllBanksList = bankList.sortedBy { it.name }
|
||||
updateState(
|
||||
currentState.copy(
|
||||
isLoading = false,
|
||||
allBanksList = sortedAllBanksList,
|
||||
popularBanksList = popularBanksList,
|
||||
paymentAmount = paymentMethodResponse?.methodDetails?.amount?.value ?: 0.0
|
||||
paymentAmount = paymentAmount
|
||||
)
|
||||
)
|
||||
recordScreenLatency(NaviPaymentAnalyticScreenName.NET_BANKING_SCREEN.screenName)
|
||||
}
|
||||
|
||||
private fun getSDKInitParams(): PaymentSdkInitParams? {
|
||||
return (paymentDataProvider.get(PaymentDataProvider.SDK_PARAMS) as? PaymentSdkInitParams)
|
||||
}
|
||||
|
||||
override fun onEvent(event: NetBankingScreenEvent) {
|
||||
when (event) {
|
||||
is NetBankingScreenEvent.OnSearchQueryChange -> {
|
||||
@@ -157,7 +153,7 @@ constructor(
|
||||
}
|
||||
is NetBankingScreenEvent.OnBankSelected -> {
|
||||
netBankingAnalytics.onBankSelected(
|
||||
selectedBank = event.bankDetails.bankTitle,
|
||||
selectedBank = event.bankEntity.name,
|
||||
isSelectedFromPopularBanks = event.isPopularBank,
|
||||
isSelectedFromFilteredList = state.value.searchQuery.text.isNotEmpty(),
|
||||
baseAttributes = getBaseAnalyticsParams()
|
||||
@@ -166,7 +162,7 @@ constructor(
|
||||
if (state.value.selectedBank == null) {
|
||||
_state.update {
|
||||
it.copy(
|
||||
selectedBank = event.bankDetails,
|
||||
selectedBank = event.bankEntity,
|
||||
isSelectedFromPopularBanks = event.isPopularBank
|
||||
)
|
||||
}
|
||||
@@ -189,9 +185,9 @@ constructor(
|
||||
if (PaymentScreenUtil.isValidJuspayResponse(payload)) {
|
||||
_effect.emit(
|
||||
NetBankingScreenEffect.NavigateToLoaderScreen(
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
token = token,
|
||||
paymentAmount = state.value.paymentAmount,
|
||||
source = paymentSdkInitParams?.paymentSource.orEmpty(),
|
||||
source = vertical,
|
||||
eventPayload = payload.toString(),
|
||||
payNowResponse = payNowResponse!!
|
||||
)
|
||||
@@ -220,7 +216,7 @@ constructor(
|
||||
|
||||
private suspend fun handleFeedbackSubmit() {
|
||||
paymentRepository.postSdkExitSignal(
|
||||
token = paymentSdkInitParams?.token.orEmpty(),
|
||||
token = token,
|
||||
data = SignalPaymentData(),
|
||||
metricInfo =
|
||||
getPMSMetricInfo(
|
||||
@@ -252,7 +248,7 @@ constructor(
|
||||
)
|
||||
val filteredBanksList =
|
||||
sortedAllBanksList.filter {
|
||||
it.bankTitle.contains(query, ignoreCase = true)
|
||||
it.name.contains(query, ignoreCase = true)
|
||||
}
|
||||
if (filteredBanksList.isEmpty()) {
|
||||
netBankingAnalytics.onNoBankFound(
|
||||
@@ -273,12 +269,12 @@ constructor(
|
||||
NetBankingPayNowRequest(
|
||||
methodName = NetBankingPaymentInstrument.PAYMENT_INSTRUMENT_TYPE,
|
||||
selectedMethodDetails =
|
||||
SelectedMethodDetails(bankName = state.value.selectedBank?.bankCode)
|
||||
SelectedMethodDetails(bankName = state.value.selectedBank?.code)
|
||||
)
|
||||
|
||||
val response =
|
||||
paymentRepository.postPayNow(
|
||||
token = paymentSdkInitParams?.token,
|
||||
token = token,
|
||||
data = data,
|
||||
metricInfo =
|
||||
getPMSMetricInfo(
|
||||
@@ -291,14 +287,6 @@ constructor(
|
||||
private suspend fun handlePayNowResponse(response: RepoResult<PayNowResponse>) {
|
||||
if (response.isSuccessWithData()) {
|
||||
payNowResponse = response.data
|
||||
paymentDataProvider.add(
|
||||
TRANSACTION_REFERENCE_ID,
|
||||
response.data?.transactionReferenceId.orEmpty()
|
||||
)
|
||||
paymentDataProvider.add(
|
||||
PAYMENT_ORDER_REFERENCE_ID,
|
||||
response.data?.paymentOrderReferenceId.orEmpty()
|
||||
)
|
||||
when (val payNowResponseData = response.data) {
|
||||
is ExternalPayNowResponse -> {
|
||||
payNowResponseData.providerPayload?.let {
|
||||
|
||||
Reference in New Issue
Block a user