From ae30fed7ff6a9cc08088e20ceed17b72c8932272 Mon Sep 17 00:00:00 2001 From: vedant aggarwal Date: Tue, 27 May 2025 19:42:28 +0530 Subject: [PATCH] NTP-17003 | Vedant Aggarwal | Handling mam tag in UPI URI (#16347) --- .../model/config/NaviPayDefaultConfig.kt | 2 + .../sendmoney/viewmodel/SendMoneyViewModel.kt | 52 ++++++++++++++----- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt index 8d0226e0c7..346d3eccde 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/common/model/config/NaviPayDefaultConfig.kt @@ -140,6 +140,8 @@ data class DefaultConfigContent( data class ConfigMessage( @SerializedName("minPaymentAmountMessage") val minPaymentAmountMessage: String = "Enter amount to pay", + @SerializedName("minPaymentAmountMessageForMinAmountTag") + val minPaymentAmountMessageForMinAmountTag: String = "Amount should be at least ₹", @SerializedName("maxPaymentAmountMessage") val maxPaymentAmountMessage: String = "Amount can’t be more than ₹20,00,000", @SerializedName("maxPaymentAmountMessageForGallery") diff --git a/android/navi-pay/src/main/kotlin/com/navi/pay/management/common/sendmoney/viewmodel/SendMoneyViewModel.kt b/android/navi-pay/src/main/kotlin/com/navi/pay/management/common/sendmoney/viewmodel/SendMoneyViewModel.kt index fe3d1797ba..66751f137f 100644 --- a/android/navi-pay/src/main/kotlin/com/navi/pay/management/common/sendmoney/viewmodel/SendMoneyViewModel.kt +++ b/android/navi-pay/src/main/kotlin/com/navi/pay/management/common/sendmoney/viewmodel/SendMoneyViewModel.kt @@ -496,8 +496,15 @@ constructor( var isRepeatPayment = false val isAmountReadOnly by lazy { - payeeEntityFromSource?.amount.orEmpty().isAmountValidForSendMoney() || - transactionType == UpiTransactionType.INTENT_PAY + // Amount should stay editable when positive minAmount is present. + val hasPositiveMinAmount = + payeeEntityFromSource?.minAmount?.toDoubleOrNull()?.let { it > 0.0 } ?: false + + val payeeAmountIsValid = payeeEntityFromSource?.amount.orEmpty().isAmountValidForSendMoney() + + val isIntentPay = transactionType == UpiTransactionType.INTENT_PAY + + !hasPositiveMinAmount && (payeeAmountIsValid || isIntentPay) } private val _isEmiConversionSupported = MutableStateFlow(false) @@ -1556,9 +1563,20 @@ constructor( _isEmiConversionSupported.update { status } } - fun isAmountValid() = - paymentAmount.value.text.isAmountValidForSendMoney() && - (paymentAmount.value.text.toDoubleOrNull() ?: 0.0) <= getMaxSendMoneyAmount() + fun isAmountValid(): Boolean { + val paymentAmountText = paymentAmount.value.text + val amount = paymentAmountText.toDoubleOrNull() ?: return false + + if (!paymentAmountText.isAmountValidForSendMoney()) return false + + val withinUpperLimit = amount <= getMaxSendMoneyAmount() + + // Parsed amount ≥ payee-specified minimum (if present). + val aboveOrEqualPayeeMin = + amount >= (payeeEntityFromSource?.minAmount?.toDoubleOrNull() ?: 0.0) + + return withinUpperLimit && aboveOrEqualPayeeMin + } private fun updateNaviPayDefaultConfig() { viewModelScope.launch(coroutineDispatcherProvider.io) { @@ -1704,6 +1722,11 @@ constructor( getMaxSendMoneyErrorMessage() to NaviPayColor.onSurfaceCritical } + numericValue < (payeeEntityFromSource?.minAmount?.toDoubleOrNull() ?: 0.0) -> { + "${naviPayDefaultConfig.config.configMessage.minPaymentAmountMessageForMinAmountTag}${payeeEntityFromSource?.minAmount?.getDisplayableAmount()}" to + NaviPayColor.onSurfaceCritical + } + else -> { naviPayDefaultConfig.config.configMessage.invalidAmountGenericMessage to null } @@ -4244,13 +4267,18 @@ constructor( private fun getMaxSendMoneyAmount(): Double { val mccValue = payeeEntity.value.mcc - return if (isQrFromUploadImage) { - naviPayDefaultConfig.config.amountLimits.sendMoneyLimitForGalleyImage - } else if (payeeEntity.value.isMerchant) { - mccValue?.let { getMaxSendMoneyAmountForMerchant(it) }!! - } else { - naviPayDefaultConfig.config.amountLimits.sendMoneyDefaultLimit - } + val sourceAmount = payeeEntityFromSource?.amount?.toDoubleOrNull()?.takeIf { it > 0 } + + val maxAllowedAmount = + when { + isQrFromUploadImage -> + naviPayDefaultConfig.config.amountLimits.sendMoneyLimitForGalleyImage + payeeEntity.value.isMerchant -> + mccValue?.let { getMaxSendMoneyAmountForMerchant(it) } ?: 0.0 + else -> naviPayDefaultConfig.config.amountLimits.sendMoneyDefaultLimit + } + + return sourceAmount?.coerceAtMost(maxAllowedAmount) ?: maxAllowedAmount } private fun getMaxSendMoneyAmountForMerchant(mccValue: String): Double {