diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/usecase/LiteAccountSyncUseCase.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/usecase/LiteAccountSyncUseCase.kt index 0f4961fc7f..24ab396bc8 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/usecase/LiteAccountSyncUseCase.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/usecase/LiteAccountSyncUseCase.kt @@ -43,6 +43,7 @@ import com.navi.pay.onboarding.account.common.repository.AccountsRepository import com.navi.pay.onboarding.account.detail.model.view.LinkedAccountEntity import com.navi.pay.onboarding.binding.model.view.NaviPayCustomerOnboardingEntity import com.navi.pay.utils.KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO +import com.navi.pay.utils.LRN_MISMATCH_ERROR import com.navi.pay.utils.UPI_LITE_DEREGISTRATION import com.navi.pay.utils.UPI_LITE_TOPUP import com.navi.pay.utils.getFormattedAmountWithDecimal @@ -72,6 +73,7 @@ constructor( private val naviCacheRepository: NaviCacheRepository, private val naviPayCustomerStatusHandler: NaviPayCustomerStatusHandler, private val upiRequestIdUseCase: UpiRequestIdUseCase, + private val accountsRepository: AccountsRepository, ) { private val INITIAL_TOPUP_POLLING_INTERVAL = 5.seconds @@ -627,6 +629,7 @@ constructor( selectedBankAccount = linkedAccountEntity, lrn = lrn, customerOnboardingEntity = customerOnboardingEntity, + pspType = pspType, ) } else -> {} @@ -639,6 +642,7 @@ constructor( selectedBankAccount: LinkedAccountEntity, lrn: String?, customerOnboardingEntity: NaviPayCustomerOnboardingEntity, + pspType: PspType, ) { naviPayAnalytics.onDevGenericEvent( event = "LiteAccountSyncUseCase_onClSuccessCallback", @@ -667,11 +671,46 @@ constructor( ) if (liteRegistrationResponse.isSuccessWithData()) { - upiLiteClHelper.registerUpiLiteWithCl( - xmlPayLoad = liteRegistrationResponse.data!!.xmlPayload, - buid = buid, - ) - checkIfClIsBoundUpdateBalance(buid = buid) + val isLrnDifferentFromRemoteLrn = + !lrn.isNullOrBlank() && lrn != liteRegistrationResponse.data?.lrn + if (isLrnDifferentFromRemoteLrn) { + /** + * If the local lrn differs from the network LRN, mark the local lrn as DEREGISTERED + * in the database and mark network lrn as PENDING_ACTIVATION. + */ + naviPayAnalytics.onDevGenericEvent( + event = LRN_MISMATCH_ERROR, + params = + mapOf( + "localLrn" to lrn.orEmpty(), + "remoteLrn" to liteRegistrationResponse.data?.lrn.orEmpty(), + "func" to "LiteAccountSyncUseCase.execute()", + ), + ) + accountsRepository.updateLiteAccountStatusByAccountIdAndLrn( + upiLiteAccountStatus = UPILiteAccountStatus.DEREGISTERED, + accountId = selectedBankAccount.accountId, + lrn = lrn.orEmpty(), + upiRequestId = upiRequestId, + ) + accountsRepository.updateLiteInfoListAfterRegistrationByAccountIdAndStatus( + lrn = liteRegistrationResponse.data?.lrn.orEmpty(), + upiLiteAccountStatus = UPILiteAccountStatus.PENDING_ACTIVATION, + initialTopUpStatus = InitialTopUpStatus.NOT_INITIATED, + lastUpdatedOn = getDateTimeStringWithYearOffset(), + accountId = selectedBankAccount.accountId, + rotation = liteRegistrationResponse.data?.rotation.orEmpty(), + deviceId = deviceInfoProvider.getDeviceData().deviceId, + pspType = pspType, + ) + naviCacheRepository.clear(KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO) + } else { + upiLiteClHelper.registerUpiLiteWithCl( + xmlPayLoad = liteRegistrationResponse.data!!.xmlPayload, + buid = buid, + ) + checkIfClIsBoundUpdateBalance(buid = buid) + } } } diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/lite/viewmodel/UpiLiteViewModel.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/lite/viewmodel/UpiLiteViewModel.kt index 3b87dd7a97..077be11450 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/lite/viewmodel/UpiLiteViewModel.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/lite/viewmodel/UpiLiteViewModel.kt @@ -155,6 +155,7 @@ import com.navi.pay.utils.DEFAULT_UPI_MODE import com.navi.pay.utils.KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO import com.navi.pay.utils.KEY_UPI_LITE_MANDATE_INFO import com.navi.pay.utils.LITE_MANDATE +import com.navi.pay.utils.LRN_MISMATCH_ERROR import com.navi.pay.utils.MONEY_ADDED_TO_UPI_LITE import com.navi.pay.utils.NAVI_PAY_DEFAULT_MCC import com.navi.pay.utils.NAVI_PAY_PURPLE_CTA_LOADER_LOTTIE @@ -3008,9 +3009,9 @@ constructor( } processLiteRegistrationResponse( + localLrn = lrn.orEmpty(), linkedAccountEntity = linkedAccountEntity, liteRegistrationResponse = liteRegistrationResponse.data!!, - lrn = lrn, upiRequestId = upiRequestId, shouldAutoInitTopUp = shouldAutoInitTopUp, initCreateAndExecuteMandate = initCreateAndExecuteMandate, @@ -3052,14 +3053,42 @@ constructor( } private suspend fun processLiteRegistrationResponse( + localLrn: String, linkedAccountEntity: LinkedAccountEntity, liteRegistrationResponse: LiteRegistrationResponse, - lrn: String?, upiRequestId: String, shouldAutoInitTopUp: Boolean, initCreateAndExecuteMandate: Boolean, pspType: PspType, ) { + /** + * If the local lrn differs from the network LRN, mark the local lrn as DEREGISTERED in the + * database. + */ + if (localLrn.isNotBlank() && localLrn != liteRegistrationResponse.lrn) { + naviPayAnalytics.onDevGenericEvent( + event = LRN_MISMATCH_ERROR, + params = + mapOf( + "localLrn" to localLrn, + "remoteLrn" to liteRegistrationResponse.lrn, + "func" to "UpiLiteViewmodel.processLiteRegistrationResponse()", + ), + ) + accountsRepository.updateLiteAccountStatusByAccountIdAndLrn( + upiLiteAccountStatus = UPILiteAccountStatus.DEREGISTERED, + accountId = linkedAccountEntity.accountId, + lrn = localLrn, + upiRequestId = upiRequestId, + ) + handleRegistrationFailedCase( + liteRegistrationResponse = liteRegistrationResponse, + linkedAccountEntity = linkedAccountEntity, + pspType = pspType, + ) + return + } + val clRegistration = upiLiteClHelper.registerUpiLiteWithCl( xmlPayLoad = liteRegistrationResponse.xmlPayload, @@ -3078,7 +3107,7 @@ constructor( // Lite registration is successful handleRegistrationSuccessCase( linkedAccountEntity = linkedAccountEntity, - lrn = lrn, + lrn = liteRegistrationResponse.lrn, liteRegistrationResponse = liteRegistrationResponse, upiRequestId = upiRequestId, initCreateAndExecuteMandate = initCreateAndExecuteMandate, diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/account/common/repository/AccountsRepository.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/account/common/repository/AccountsRepository.kt index 487814ea43..134d4052f3 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/account/common/repository/AccountsRepository.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/onboarding/account/common/repository/AccountsRepository.kt @@ -181,6 +181,39 @@ constructor( } } + suspend fun updateLiteAccountStatusByAccountIdAndLrn( + upiLiteAccountStatus: UPILiteAccountStatus, + accountId: String, + lrn: String, + upiRequestId: String?, + ) { + val activeAccountsForAccountId = + accountDao.getAccountByAccountIdAndStatus( + accountId = accountId, + status = AccountStatus.ACTIVE, + ) + + val upiLiteInfoList = activeAccountsForAccountId.upiLiteInfo.toMutableList() + + // Updating the account status for the lrn + upiLiteInfoList + .indexOfFirst { it.lrn == lrn } + .let { + if (it != -1) { + upiLiteInfoList[it] = + upiLiteInfoList[it].copy( + accountStatus = upiLiteAccountStatus, + initialTopUpUpiRequestId = upiRequestId ?: "", + ) + accountDao.updateLiteInfoListByAccountIdAndStatus( + accountId = accountId, + accountStatus = AccountStatus.ACTIVE, + upiLiteInfo = upiLiteInfoList, + ) + } + } + } + suspend fun updateLiteAccountStatusAndDeregistrationUpiRequestIdByAccountIdAndLrn( upiLiteAccountStatus: UPILiteAccountStatus, accountId: String, diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt index 2e37ec0f95..342196005e 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/utils/NaviPayConstants.kt @@ -608,3 +608,6 @@ const val GOLD_ROUND_OFF_AMOUNT = "Round-off amount" // External id error const val ERR_FAILED_TO_FETCH_EXTERNAL_CUSTOMER_ID = "ERR_FAILED_TO_FETCH_EXTERNAL_CUSTOMER_ID" + +// Lrn mismatch error +const val LRN_MISMATCH_ERROR = "lrn_mismatch_error"