NTP-15268 | Qr mandate account selection (#13930)
Co-authored-by: Ujjwal Kumar <ujjwal.kumar@navi.com>
This commit is contained in:
@@ -1533,6 +1533,18 @@ class NaviPayAnalytics private constructor() {
|
||||
eventValues = mapOf("qrContent" to qrContent)
|
||||
)
|
||||
}
|
||||
|
||||
fun onUrlTypeQROpenLinkClicked() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPay_QrScanner_UrlTypeQRScanned_Openlink"
|
||||
)
|
||||
}
|
||||
|
||||
fun onUrlTypeQRCancelClicked() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
eventName = "NaviPay_QrScanner_UrlTypeQRScanned_Cancel"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
inner class NaviPayBankDetailsInput {
|
||||
|
||||
@@ -12,6 +12,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.navi.base.cache.datastore.DataStoreHelper
|
||||
import com.navi.base.utils.DateUtils
|
||||
import com.navi.base.utils.ResourceProvider
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccess
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
import com.navi.pay.R
|
||||
@@ -19,6 +20,7 @@ import com.navi.pay.analytics.NaviPayAnalytics
|
||||
import com.navi.pay.analytics.NaviPayAnalytics.Companion.NAVI_PAY_PENDING_MANDATE_DETAILS
|
||||
import com.navi.pay.common.connectivity.NaviPayNetworkConnectivity
|
||||
import com.navi.pay.common.model.network.ValidateVpaRequest
|
||||
import com.navi.pay.common.model.network.ValidateVpaResponse
|
||||
import com.navi.pay.common.repository.CommonRepository
|
||||
import com.navi.pay.common.setup.NaviPayCustomerStatusHandler
|
||||
import com.navi.pay.common.setup.model.NaviPayCustomerStatus
|
||||
@@ -33,6 +35,7 @@ import com.navi.pay.management.common.sendmoney.model.network.BlockSpamUserReque
|
||||
import com.navi.pay.management.common.sendmoney.model.view.BankAccountsState
|
||||
import com.navi.pay.management.common.sendmoney.model.view.EligibilityState
|
||||
import com.navi.pay.management.common.sendmoney.model.view.PayeeEntity
|
||||
import com.navi.pay.management.common.sendmoney.util.AccountEligibilityMerchantHelper
|
||||
import com.navi.pay.management.mandate.model.network.CreateMandateRequest
|
||||
import com.navi.pay.management.mandate.model.network.MandateDetailRequest
|
||||
import com.navi.pay.management.mandate.model.network.ReviewMandateRequest
|
||||
@@ -49,14 +52,12 @@ import com.navi.pay.management.mandate.repository.MandateRepository
|
||||
import com.navi.pay.npcicl.CredDataProvider
|
||||
import com.navi.pay.npcicl.NpciRepository
|
||||
import com.navi.pay.npcicl.NpciResult
|
||||
import com.navi.pay.onboarding.account.add.model.view.AccountType
|
||||
import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity
|
||||
import com.navi.pay.utils.DATE_TIME_FORMAT_DATE_MONTH_YEAR_WITHOUT_SEPARATOR
|
||||
import com.navi.pay.utils.DATE_TIME_FORMAT_YEAR_MONTH_DATE_WITH_SLASH_SEPARATOR
|
||||
import com.navi.pay.utils.DS_KEY_NAVI_PAY_CUSTOMER_STATUS
|
||||
import com.navi.pay.utils.NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE
|
||||
import com.navi.pay.utils.REQUEST_TYPE_MANDATE
|
||||
import com.navi.pay.utils.RESOURCE_DEFAULT_ID
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
@@ -91,7 +92,8 @@ constructor(
|
||||
private val upiRequestIdUseCase: UpiRequestIdUseCase,
|
||||
private val naviPayCustomerStatusHandler: NaviPayCustomerStatusHandler,
|
||||
private val dataStoreHelper: DataStoreHelper,
|
||||
private val resourceProvider: ResourceProvider
|
||||
private val resourceProvider: ResourceProvider,
|
||||
private val accountEligibilityMerchantHelper: AccountEligibilityMerchantHelper,
|
||||
) : NaviPayBaseVM() {
|
||||
|
||||
private val naviPayAnalytics: NaviPayAnalytics.NaviPayManageAutoPay =
|
||||
@@ -229,20 +231,34 @@ constructor(
|
||||
private fun initMandateEntityAndOpenDetailScreen() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
initMandateEntity()
|
||||
getLinkedAccountsInfo()
|
||||
validateVpaAndGetLinkedAccountsInfo()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLinkedAccountsInfo() {
|
||||
private fun validateVpaAndGetLinkedAccountsInfo() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val validateVpaAPIResponse =
|
||||
validateVpaUseCase.execute(
|
||||
request =
|
||||
ValidateVpaRequest(
|
||||
deviceData = deviceInfoProvider.getDeviceData(),
|
||||
merchantCustomerId = deviceInfoProvider.getMerchantCustomerId(),
|
||||
vpa = mandateEntity?.payeeVpa.orEmpty()
|
||||
),
|
||||
screenName = screenName
|
||||
)
|
||||
|
||||
linkedAccountsUseCase.execute(screenName = screenName).collect {
|
||||
val asyncJobList = mutableListOf<Deferred<Unit>>()
|
||||
asyncJobList.add(
|
||||
async {
|
||||
executeLinkedAccountsFetchAndUpdateBankAccountState(linkedAccountsInDB = it)
|
||||
executeLinkedAccountsFetchAndUpdateBankAccountState(
|
||||
linkedAccountsInDB = it,
|
||||
validateVpaResponse = validateVpaAPIResponse.data
|
||||
)
|
||||
}
|
||||
)
|
||||
asyncJobList.add(async { validateVpaAndUpdateIsMerchantStateValues() })
|
||||
asyncJobList.add(async { updateIsMerchantStateValues(validateVpaAPIResponse) })
|
||||
asyncJobList.awaitAll()
|
||||
|
||||
updateUIState(uiState = MandateDetailUIStateOfPendingCategory.MandateDetail)
|
||||
@@ -258,12 +274,16 @@ constructor(
|
||||
payeeEntity?.let { mandateEntity = it.toMandateEntity() }
|
||||
}
|
||||
|
||||
private fun executeLinkedAccountsFetchAndUpdateBankAccountState(
|
||||
linkedAccountsInDB: List<LinkedAccountEntity>
|
||||
private suspend fun executeLinkedAccountsFetchAndUpdateBankAccountState(
|
||||
linkedAccountsInDB: List<LinkedAccountEntity>,
|
||||
validateVpaResponse: ValidateVpaResponse?
|
||||
) {
|
||||
updateBankAccountsState(state = BankAccountsState.Loading)
|
||||
val postProcessedLinkedAccounts =
|
||||
postProcessLinkedAccounts(linkedAccounts = linkedAccountsInDB)
|
||||
postProcessLinkedAccounts(
|
||||
linkedAccounts = linkedAccountsInDB,
|
||||
validateVpaResponse = validateVpaResponse
|
||||
)
|
||||
|
||||
if (postProcessedLinkedAccounts.isEmpty()) {
|
||||
updateBankAccountsState(state = BankAccountsState.NoAccountLinked)
|
||||
@@ -276,24 +296,32 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun postProcessLinkedAccounts(
|
||||
linkedAccounts: List<LinkedAccountEntity>
|
||||
private suspend fun postProcessLinkedAccounts(
|
||||
linkedAccounts: List<LinkedAccountEntity>,
|
||||
validateVpaResponse: ValidateVpaResponse?
|
||||
): List<LinkedAccountEntity> {
|
||||
|
||||
// Account eligibility status update
|
||||
val updatedLinkedAccountsWithEligibility =
|
||||
updateAccountEligibilityStatusInLinkedAccounts(linkedAccounts = linkedAccounts)
|
||||
updateAccountEligibilityStatusInLinkedAccounts(
|
||||
linkedAccounts = linkedAccounts,
|
||||
validateVpaResponse = validateVpaResponse
|
||||
)
|
||||
|
||||
return updatedLinkedAccountsWithEligibility
|
||||
}
|
||||
|
||||
private fun updateAccountEligibilityStatusInLinkedAccounts(
|
||||
linkedAccounts: List<LinkedAccountEntity>
|
||||
private suspend fun updateAccountEligibilityStatusInLinkedAccounts(
|
||||
linkedAccounts: List<LinkedAccountEntity>,
|
||||
validateVpaResponse: ValidateVpaResponse?
|
||||
): List<LinkedAccountEntity> {
|
||||
val updatedLinkedAccounts =
|
||||
linkedAccounts.map { linkedAccount ->
|
||||
val eligibilityState =
|
||||
getEligibilityStateForLinkedAccount(linkedAccountEntity = linkedAccount)
|
||||
getEligibilityStateForLinkedAccount(
|
||||
linkedAccountEntity = linkedAccount,
|
||||
validateVpaResponse = validateVpaResponse
|
||||
)
|
||||
linkedAccount.eligibilityState = eligibilityState
|
||||
linkedAccount
|
||||
}
|
||||
@@ -301,8 +329,9 @@ constructor(
|
||||
return updatedLinkedAccounts
|
||||
}
|
||||
|
||||
private fun getEligibilityStateForLinkedAccount(
|
||||
linkedAccountEntity: LinkedAccountEntity
|
||||
private suspend fun getEligibilityStateForLinkedAccount(
|
||||
linkedAccountEntity: LinkedAccountEntity,
|
||||
validateVpaResponse: ValidateVpaResponse?
|
||||
): EligibilityState {
|
||||
|
||||
// PIN set check
|
||||
@@ -313,28 +342,31 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
val isAccountOfTypeCreditCardOrCreditLine =
|
||||
AccountType.isAccountOfTypeCreditCardOrCreditLine(
|
||||
type = linkedAccountEntity.accountType
|
||||
)
|
||||
|
||||
// Credit account check
|
||||
if (isAccountOfTypeCreditCardOrCreditLine) {
|
||||
return EligibilityState(
|
||||
isAccountEligible = false,
|
||||
inEligibilityReasonResId =
|
||||
when (linkedAccountEntity.accountType) {
|
||||
AccountType.CREDIT.name -> R.string.np_credit_card_transaction_not_supported
|
||||
AccountType.UPICREDIT.name ->
|
||||
R.string.np_credit_line_transaction_not_supported
|
||||
else -> RESOURCE_DEFAULT_ID
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// For create mandate, all accounts are eligible
|
||||
// For create mandate, accounts are eligible according to feature tags
|
||||
return if (isPendingMandateOfTypeCreate) {
|
||||
EligibilityState(isAccountEligible = true)
|
||||
if (validateVpaResponse == null) {
|
||||
return EligibilityState(isAccountEligible = true)
|
||||
} else {
|
||||
val accountTypeEligibilityMap =
|
||||
accountEligibilityMerchantHelper.fetchAccountTypeEligibilityMap(
|
||||
featureTags = validateVpaResponse.featureTags,
|
||||
screenName = screenName
|
||||
)
|
||||
return EligibilityState(
|
||||
isAccountEligible =
|
||||
accountEligibilityMerchantHelper.getAccountEligibility(
|
||||
eligibility =
|
||||
accountTypeEligibilityMap[linkedAccountEntity.accountType],
|
||||
amount = mandateEntity?.amount?.toDouble() ?: 0.0
|
||||
),
|
||||
inEligibilityReason =
|
||||
accountEligibilityMerchantHelper.getIneligibilityReason(
|
||||
eligibility =
|
||||
accountTypeEligibilityMap[linkedAccountEntity.accountType],
|
||||
accountType = linkedAccountEntity.accountType
|
||||
)
|
||||
)
|
||||
}
|
||||
} else { // For approve mandate, only payer VPA account is eligible
|
||||
EligibilityState(isAccountEligible = linkedAccountEntity.vpa == mandateEntity?.payerVpa)
|
||||
}
|
||||
@@ -350,18 +382,9 @@ constructor(
|
||||
updateSelectedBankAccount(selectedBankAccount = defaultSelectedAccount)
|
||||
}
|
||||
|
||||
private suspend fun validateVpaAndUpdateIsMerchantStateValues() {
|
||||
|
||||
val validateVpaAPIResponse =
|
||||
validateVpaUseCase.execute(
|
||||
request =
|
||||
ValidateVpaRequest(
|
||||
deviceData = deviceInfoProvider.getDeviceData(),
|
||||
merchantCustomerId = deviceInfoProvider.getMerchantCustomerId(),
|
||||
vpa = mandateEntity?.payeeVpa.orEmpty()
|
||||
),
|
||||
screenName = screenName
|
||||
)
|
||||
private fun updateIsMerchantStateValues(
|
||||
validateVpaAPIResponse: RepoResult<ValidateVpaResponse>
|
||||
) {
|
||||
|
||||
// If mandate name is not present, then use the name from validateVpa API response
|
||||
mandateEntity =
|
||||
|
||||
@@ -416,6 +416,7 @@ fun QrScannerScreen(
|
||||
try {
|
||||
closeSheet()
|
||||
delay(200.milliseconds)
|
||||
naviPayAnalytics.onUrlTypeQROpenLinkClicked()
|
||||
// For closing bottom sheet before navigating
|
||||
uriHandler.openUri(it)
|
||||
} catch (e: Exception) {
|
||||
@@ -428,6 +429,7 @@ fun QrScannerScreen(
|
||||
onUrlRedirectionSecondaryCtaClicked = {
|
||||
closeSheet()
|
||||
qrScannerViewModel.isQrCodeProcessing.set(false)
|
||||
naviPayAnalytics.onUrlTypeQRCancelClicked()
|
||||
}
|
||||
)
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user