From cf8d030cfaccd8576fc3ab79fe9df91a77e915da Mon Sep 17 00:00:00 2001 From: samiuelson Date: Fri, 6 Dec 2024 09:54:46 +0100 Subject: [PATCH] Get order from db instead of caching in memory --- .../home/totals/WooPosTotalsRepository.kt | 14 +++++- .../home/totals/WooPosTotalsViewModel.kt | 10 ++--- .../home/totals/WooPosTotalsRepositoryTest.kt | 45 +++++++++---------- .../home/totals/WooPosTotalsViewModelTest.kt | 5 ++- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepository.kt index a197ca2aece..d94b80978ab 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepository.kt @@ -1,6 +1,8 @@ package com.woocommerce.android.ui.woopos.home.totals import com.woocommerce.android.model.Order +import com.woocommerce.android.model.OrderMapper +import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.orders.creation.OrderCreateEditRepository import com.woocommerce.android.ui.woopos.common.data.WooPosGetProductById import com.woocommerce.android.util.DateUtils @@ -8,13 +10,17 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.async import kotlinx.coroutines.withContext +import org.wordpress.android.fluxc.store.WCOrderStore import java.util.Date import javax.inject.Inject class WooPosTotalsRepository @Inject constructor( private val orderCreateEditRepository: OrderCreateEditRepository, private val dateUtils: DateUtils, - private val getProductById: WooPosGetProductById + private val getProductById: WooPosGetProductById, + private val orderStore: WCOrderStore, + private val selectedSite: SelectedSite, + private val orderMapper: OrderMapper, ) { private var orderCreationJob: Deferred>? = null @@ -59,6 +65,12 @@ class WooPosTotalsRepository @Inject constructor( } } + suspend fun getOrderById(orderId: Long) = withContext(IO) { + orderStore.getOrderByIdAndSite(orderId, selectedSite.get())?.let { + orderMapper.toAppModel(it) + } + } + private companion object { /** * This magic value used to indicate that we don't want to send subtotals and totals diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt index 354978dccec..14767e9141a 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModel.kt @@ -69,7 +69,7 @@ class WooPosTotalsViewModel @Inject constructor( } private val uiState: MutableStateFlow = - savedState.getStateFlow( + savedState.getStateFlow( scope = viewModelScope, initialValue = InitialState, key = "woo_pos_totals_view_state" @@ -83,8 +83,6 @@ class WooPosTotalsViewModel @Inject constructor( key = KEY_STATE, ) - private var order: Order? = null - private var isTTPPaymentInProgress: Boolean get() = savedState.get(KEY_TTP_PAYMENT_IN_PROGRESS) == true set(value) { @@ -159,11 +157,12 @@ class WooPosTotalsViewModel @Inject constructor( WooPosTotalsUIEvent.RetryFailedTransactionClicked -> viewModelScope.launch { cancelPaymentAction() childrenToParentEventSender.sendToParent(ChildToParentEvent.RetryFailedPaymentClicked) + val order = totalsRepository.getOrderById(dataState.value.orderId) if (order == null) { uiState.value = InitialState childrenToParentEventSender.sendToParent(ChildToParentEvent.BackFromCheckoutToCartClicked) } else { - uiState.value = buildWooPosTotalsViewState(order!!) + uiState.value = buildWooPosTotalsViewState(order) collectPayment() } } @@ -181,8 +180,6 @@ class WooPosTotalsViewModel @Inject constructor( if (cardReaderFacade.readerStatus.value is Connected) { val state = uiState.value check(state is WooPosTotalsViewState.Totals) - val orderId = dataState.value.orderId - check(orderId != EMPTY_ORDER_ID) check(uiState.value is WooPosTotalsViewState.Totals) createCardReaderPaymentController(dataState.value.orderId) cardReaderPaymentController?.start() @@ -282,7 +279,6 @@ class WooPosTotalsViewModel @Inject constructor( onSuccess = { order -> dataState.value = dataState.value.copy(orderId = order.id) uiState.value = buildWooPosTotalsViewState(order) - this@WooPosTotalsViewModel.order = order analyticsTracker.track(WooPosAnalyticsEvent.Event.OrderCreationSuccess) collectPayment() }, diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepositoryTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepositoryTest.kt index 2d5c07548ea..f65e5c1ed69 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepositoryTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsRepositoryTest.kt @@ -1,6 +1,8 @@ package com.woocommerce.android.ui.woopos.home.totals import com.woocommerce.android.model.Order +import com.woocommerce.android.model.OrderMapper +import com.woocommerce.android.tools.SelectedSite import com.woocommerce.android.ui.orders.creation.OrderCreateEditRepository import com.woocommerce.android.ui.products.ProductHelper import com.woocommerce.android.ui.products.ProductType @@ -16,12 +18,16 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import org.wordpress.android.fluxc.store.WCOrderStore class WooPosTotalsRepositoryTest { private val orderCreateEditRepository: OrderCreateEditRepository = mock() private val getProductById: WooPosGetProductById = mock() private val dateUtils: DateUtils = mock() + private val orderStore: WCOrderStore = mock() + private val selectedSite: SelectedSite = mock() + private val orderMapper: OrderMapper = mock() private lateinit var repository: WooPosTotalsRepository @@ -33,11 +39,7 @@ class WooPosTotalsRepositoryTest { @Test fun `given empty product list, when createOrderWithProducts called, then return error`() = runTest { // GIVEN - repository = WooPosTotalsRepository( - orderCreateEditRepository, - dateUtils, - getProductById - ) + repository = createRepository() val productIds = emptyList() // WHEN @@ -50,11 +52,7 @@ class WooPosTotalsRepositoryTest { @Test fun `given product ids without duplicates, when createOrderWithProducts, then items all quantity one`() = runTest { // GIVEN - repository = WooPosTotalsRepository( - orderCreateEditRepository, - dateUtils, - getProductById - ) + repository = createRepository() val productIds = listOf(1L, 2L, 3L) whenever(getProductById(1L)).thenReturn(product1) @@ -79,11 +77,7 @@ class WooPosTotalsRepositoryTest { @Test fun `given product id, when createOrderWithProducts, then item name matches original product`() = runTest { // GIVEN - repository = WooPosTotalsRepository( - orderCreateEditRepository, - dateUtils, - getProductById - ) + repository = createRepository() val productIds = listOf(1L) whenever(getProductById(1L)).thenReturn(product1) @@ -105,11 +99,7 @@ class WooPosTotalsRepositoryTest { @Test fun `given product ids with duplicates, when createOrderWithProducts, then items quantity is correct`() = runTest { // GIVEN - repository = WooPosTotalsRepository( - orderCreateEditRepository, - dateUtils, - getProductById - ) + repository = createRepository() val productIds = listOf(1L, 1L, 2L, 3L, 3L, 3L) whenever(getProductById(1L)).thenReturn(product1) @@ -133,11 +123,7 @@ class WooPosTotalsRepositoryTest { @Test fun `given product ids, when createOrder with some invalid ids, then return failure`() = runTest { // GIVEN - repository = WooPosTotalsRepository( - orderCreateEditRepository, - dateUtils, - getProductById - ) + repository = createRepository() val productIds = listOf(1L, -1L, 3L) val mockOrder: Order = mock() whenever(orderCreateEditRepository.createOrUpdateOrder(any(), eq(""))).thenReturn(Result.success(mockOrder)) @@ -151,4 +137,13 @@ class WooPosTotalsRepositoryTest { assertThat(result.exceptionOrNull()?.message).isEqualTo("Invalid product ID: -1") verify(orderCreateEditRepository, never()).createOrUpdateOrder(any(), eq("")) } + + private fun createRepository() = WooPosTotalsRepository( + orderCreateEditRepository, + dateUtils, + getProductById, + orderStore, + selectedSite, + orderMapper, + ) } diff --git a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModelTest.kt b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModelTest.kt index 9f7913cf47e..ec8dda7c0e9 100644 --- a/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModelTest.kt +++ b/WooCommerce/src/test/kotlin/com/woocommerce/android/ui/woopos/home/totals/WooPosTotalsViewModelTest.kt @@ -834,7 +834,7 @@ class WooPosTotalsViewModelTest { } @Test - fun `given payment failed, when retry clicked, then should retry`() { + fun `given payment failed, when retry clicked, then should retry`() = runTest { // GIVEN whenever(resourceProvider.getString(R.string.woopos_success_totals_payment_processing_title)) .thenReturn("Processing payment") @@ -906,7 +906,7 @@ class WooPosTotalsViewModelTest { verify(childrenToParentEventSender).sendToParent(ChildToParentEvent.ExitOrderAfterFailedTransactionClicked) } - private fun createViewModelAndSetupForSuccessfulOrderCreation( + private suspend fun createViewModelAndSetupForSuccessfulOrderCreation( controllerFactory: CardReaderPaymentControllerFactory = paymentControllerFactory ): WooPosTotalsViewModel { whenever(resourceProvider.getString(R.string.woopos_success_totals_error_reader_not_connected_title)) @@ -952,6 +952,7 @@ class WooPosTotalsViewModelTest { val parentToChildrenEventReceiver: WooPosParentToChildrenEventReceiver = mock { on { events }.thenReturn(parentToChildrenEventFlow) } + whenever(totalsRepository.getOrderById(orderId)).thenReturn(order) return createViewModel( totalsRepository = totalsRepository, priceFormat = priceFormat,