NTP-63647 | Sidharth Bamba | Bug fix for timestamp changes after scratch card (#16462)
This commit is contained in:
@@ -636,5 +636,19 @@ val NAVI_PAY_APP_DATABASE_MIGRATION_21_22 =
|
||||
db.execSQL(
|
||||
"ALTER TABLE `$NAVI_PAY_DATABASE_VPA_TABLE_NAME` ADD COLUMN `vpaReason` TEXT NOT NULL DEFAULT 'UNKNOWN'"
|
||||
)
|
||||
|
||||
/*
|
||||
* Migration to fix orderTimestamp format inconsistency causing sorting issues.
|
||||
*
|
||||
* Problem: Order history had mixed timestamp formats:
|
||||
* - Network sync: UTC format (2025-06-18T12:10:19.673Z)
|
||||
* - Local transactions: IST format (2025-06-18T17:34:34.452+05:30)
|
||||
*
|
||||
* Solution: Force re-sync from server to get all data in consistent UTC format.
|
||||
* This ensures proper chronological sorting in order history.
|
||||
*/
|
||||
db.execSQL(
|
||||
"DELETE FROM $NAVI_PAY_DATABASE_SYNC_TABLE_NAME WHERE syncKey = '$NAVI_PAY_SYNC_TABLE_ORDER_HISTORY_KEY'"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -779,6 +779,10 @@ constructor(
|
||||
orderEntity?.let { currentOrder ->
|
||||
val updateOrderEntity =
|
||||
currentOrder.copy(
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
epochMillis = currentOrder.orderTimestamp.millis
|
||||
),
|
||||
orderDetails =
|
||||
currentOrder.orderDetails.let { currentOrderDetails ->
|
||||
currentOrderDetails.copy(
|
||||
@@ -792,12 +796,6 @@ constructor(
|
||||
}
|
||||
)
|
||||
},
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
epochMillis = currentOrder.orderTimestamp.millis
|
||||
),
|
||||
// updating timestamp here to maintain consistent format in
|
||||
// local db if the db entry is not updated by api response
|
||||
)
|
||||
orderDetailsRepository.updateOrder(orderEntity = updateOrderEntity)
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.navi.pay.tstore.list.model.view.OrderPaymentMode
|
||||
import com.navi.pay.tstore.list.model.view.OrderStatusOfView
|
||||
import com.navi.pay.utils.NAVI_PAY_TRANSACTION_HISTORY_TAG_SEPARATOR
|
||||
import com.navi.rr.utils.ext.toJson
|
||||
import org.joda.time.DateTimeZone
|
||||
|
||||
internal fun TransactionEntity.toOrderEntity(tstoreOrderId: String): OrderEntity =
|
||||
OrderEntity(
|
||||
@@ -49,7 +50,7 @@ internal fun TransactionEntity.toOrderEntity(tstoreOrderId: String): OrderEntity
|
||||
orderTitle = getOrderTitleToDisplay(),
|
||||
paymentMode = OrderPaymentMode.UPI,
|
||||
orderDescription = getOrderDescriptionToDisplay(),
|
||||
orderTimestamp = transactionTimestamp,
|
||||
orderTimestamp = transactionTimestamp.withZone(DateTimeZone.UTC),
|
||||
orderImageUrl =
|
||||
otherUserInfo.split(NAVI_PAY_TRANSACTION_HISTORY_TAG_SEPARATOR).getOrElse(3) {
|
||||
""
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.navi.payments.shared.core.network.service.PaymentsSharedRetrofitServi
|
||||
import com.navi.payments.shared.feature.arc.model.network.ArcExactOfferRequest
|
||||
import com.navi.payments.shared.feature.arc.model.network.ArcExactOfferResponse
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OrderDetailsRepository
|
||||
@Inject
|
||||
@@ -50,6 +51,10 @@ constructor(
|
||||
return orderDao.getOrderEntity(orderId)
|
||||
}
|
||||
|
||||
fun getOrderEntityAsFlow(orderId: String): Flow<OrderEntity?> {
|
||||
return orderDao.getOrderEntityAsFlow(orderId)
|
||||
}
|
||||
|
||||
suspend fun updateNotificationsPermission(
|
||||
notificationSettings: List<NotificationSettings>
|
||||
): RepoResult<Unit> {
|
||||
|
||||
@@ -191,10 +191,14 @@ import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -252,8 +256,16 @@ constructor(
|
||||
savedStateHandle.get<String>("orderReferenceId")?.takeIf { it.isNotEmpty() }
|
||||
?: naviPayActivityDataProvider.getString("orderReferenceId").orEmpty()
|
||||
|
||||
private val _orderEntity = MutableStateFlow<OrderEntity?>(null)
|
||||
val orderEntity = _orderEntity.asStateFlow()
|
||||
val orderEntity =
|
||||
orderDetailsRepository
|
||||
.getOrderEntityAsFlow(orderId = orderReferenceId)
|
||||
.flowOn(dispatcherProvider.io)
|
||||
.distinctUntilChanged()
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
initialValue = null,
|
||||
)
|
||||
|
||||
private val _linkedAccounts = MutableStateFlow<List<LinkedAccountEntity>>(emptyList())
|
||||
val linkedAccounts = _linkedAccounts.asStateFlow()
|
||||
@@ -588,13 +600,25 @@ constructor(
|
||||
|
||||
private suspend fun getOrderDetails(): IsError {
|
||||
|
||||
val orderDetails = orderDetailsRepository.getOrderEntity(orderId = orderReferenceId)
|
||||
val orderDetails = orderEntity.first { it != null }
|
||||
if (orderDetails == null) {
|
||||
_clearAndNavigateBack.emit(true)
|
||||
return true
|
||||
}
|
||||
|
||||
updateOrderEntity(orderEntity = orderDetails)
|
||||
if (orderDetails.paymentStatus.isFailed() || orderDetails.orderStatusOfView.isFailed()) {
|
||||
val orderErrorEntity =
|
||||
orderErrorMappingManager.getErrorEntityByCode(
|
||||
errorCode = orderDetails.orderDetails.errorCode
|
||||
)
|
||||
naviPayAnalytics.onOrderErrorDetailsFetchedDevEvent(
|
||||
errorCode = orderDetails.orderDetails.errorCode.orEmpty(),
|
||||
orderErrorEntity = orderErrorEntity,
|
||||
isExperimentEnabled = true,
|
||||
productType = orderDetails.productType,
|
||||
)
|
||||
_orderErrorEntity.update { orderErrorEntity }
|
||||
}
|
||||
|
||||
_orderDetailsMetadataProvider.update {
|
||||
OrderDetailsMetadataProvider(orderEntity = orderEntity.value)
|
||||
@@ -1578,11 +1602,15 @@ constructor(
|
||||
val arcExactOfferResponseData = arcExactOfferResponse.data!!
|
||||
|
||||
val updatedOrderEntity =
|
||||
_orderEntity.value?.copy(
|
||||
orderEntity.value?.copy(
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
orderEntity.value?.orderTimestamp?.millis ?: 0L
|
||||
),
|
||||
orderDetails =
|
||||
orderEntity.value
|
||||
?.orderDetails!!
|
||||
.copy(isArcProtected = arcExactOfferResponseData.isArcProtected.orFalse())
|
||||
.copy(isArcProtected = arcExactOfferResponseData.isArcProtected.orFalse()),
|
||||
)
|
||||
|
||||
updateOrderEntity(orderEntity = updatedOrderEntity)
|
||||
@@ -1673,7 +1701,11 @@ constructor(
|
||||
(orderEntity.value?.paymentStatus != newPaymentStatus)
|
||||
|
||||
val updatedOrderEntity =
|
||||
_orderEntity.value?.copy(
|
||||
orderEntity.value?.copy(
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
epochMillis = orderEntity.value?.orderTimestamp?.millis ?: 0L
|
||||
),
|
||||
orderDetails =
|
||||
orderEntity.value
|
||||
?.orderDetails!!
|
||||
@@ -1682,11 +1714,8 @@ constructor(
|
||||
paymentStatus = newPaymentStatus,
|
||||
)
|
||||
|
||||
updateOrderEntity(orderEntity = updatedOrderEntity)
|
||||
|
||||
if (isStatusChanged) {
|
||||
orderDetailsRepository.updateOrder(orderEntity = orderEntity.value!!)
|
||||
getOrderDetails()
|
||||
updateOrderEntity(orderEntity = updatedOrderEntity!!)
|
||||
prepareArcStatusWidgetProperties()
|
||||
if (
|
||||
newOrderStatusOfView != OrderStatusOfView.Pending ||
|
||||
@@ -1700,6 +1729,7 @@ constructor(
|
||||
launch { liteAccountSyncUseCase.execute(screenName = screenName) }
|
||||
}
|
||||
}
|
||||
preparePaymentStatusWidgetProperties()
|
||||
}
|
||||
|
||||
prepareRefundStatusWidgetProperties()
|
||||
@@ -1948,9 +1978,13 @@ constructor(
|
||||
|
||||
updateScratchCardStatus(ScratchCardState.None)
|
||||
|
||||
_orderEntity.value?.let { currentOrder ->
|
||||
orderEntity.value?.let { currentOrder ->
|
||||
val updatedOrder =
|
||||
currentOrder.copy(
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
currentOrder.orderTimestamp.millis
|
||||
),
|
||||
orderDetails =
|
||||
currentOrder.orderDetails.let { currentOrderDetails ->
|
||||
currentOrderDetails.copy(
|
||||
@@ -1966,17 +2000,9 @@ constructor(
|
||||
}
|
||||
)
|
||||
},
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
epochMillis = currentOrder.orderTimestamp.millis
|
||||
),
|
||||
// updating timestamp here to maintain consistent format in
|
||||
// local db if the db entry is not updated by api response
|
||||
)
|
||||
updateOrderEntity(updatedOrder)
|
||||
orderDetailsRepository.updateOrder(orderEntity = updatedOrder)
|
||||
}
|
||||
|
||||
_orderEntity.value?.let { orderDetailsRepository.updateOrder(it) }
|
||||
}
|
||||
|
||||
is ScratchCardBackResponse.Success -> {
|
||||
@@ -2005,9 +2031,13 @@ constructor(
|
||||
}
|
||||
)
|
||||
|
||||
_orderEntity.value?.let { currentOrder ->
|
||||
orderEntity.value?.let { currentOrder ->
|
||||
val updatedOrder =
|
||||
currentOrder.copy(
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
currentOrder.orderTimestamp.millis
|
||||
),
|
||||
orderDetails =
|
||||
currentOrder.orderDetails.let { currentOrderDetails ->
|
||||
currentOrderDetails.copy(
|
||||
@@ -2023,17 +2053,9 @@ constructor(
|
||||
}
|
||||
)
|
||||
},
|
||||
orderTimestamp =
|
||||
getDateTimeObjectFromEpochString(
|
||||
epochMillis = currentOrder.orderTimestamp.millis
|
||||
),
|
||||
// updating timestamp here to maintain consistent format in
|
||||
// local db if the db entry is not updated by api response
|
||||
)
|
||||
updateOrderEntity(updatedOrder)
|
||||
orderDetailsRepository.updateOrder(orderEntity = updatedOrder)
|
||||
}
|
||||
|
||||
_orderEntity.value?.let { orderDetailsRepository.updateOrder(it) }
|
||||
}
|
||||
|
||||
else -> {}
|
||||
@@ -2045,7 +2067,7 @@ constructor(
|
||||
private suspend fun updateOrderEntity(orderEntity: OrderEntity?) {
|
||||
if (orderEntity == null) return
|
||||
|
||||
_orderEntity.update { orderEntity }
|
||||
orderDetailsRepository.updateOrder(orderEntity = orderEntity)
|
||||
|
||||
if (orderEntity.paymentStatus.isFailed() || orderEntity.orderStatusOfView.isFailed()) {
|
||||
val orderErrorEntity =
|
||||
|
||||
@@ -32,6 +32,11 @@ interface OrderDao {
|
||||
)
|
||||
suspend fun getOrderEntity(orderId: String): OrderEntity?
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM $NAVI_PAY_DATABASE_T_STORE_ORDER_HISTORY_TABLE_NAME WHERE orderReferenceId = :orderId"
|
||||
)
|
||||
fun getOrderEntityAsFlow(orderId: String): Flow<OrderEntity?>
|
||||
|
||||
@Update suspend fun updateOrderEntity(orderEntity: OrderEntity)
|
||||
|
||||
@Query(
|
||||
|
||||
Reference in New Issue
Block a user