From 1e6eb5c4ed41d04e31c0c66907d09e87bc3dd29a Mon Sep 17 00:00:00 2001 From: Hafiz Rahman Date: Thu, 9 Jan 2025 18:17:43 +0700 Subject: [PATCH 1/9] Refactor result from bulk update to handled various cases. --- .../ui/orders/list/BulkUpdateOrderResult.kt | 16 +++++ .../ui/orders/list/OrderListRepository.kt | 28 ++++---- .../ui/orders/list/OrderListViewModel.kt | 68 ++++++++++++++----- WooCommerce/src/main/res/values/strings.xml | 3 + 4 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/BulkUpdateOrderResult.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/BulkUpdateOrderResult.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/BulkUpdateOrderResult.kt new file mode 100644 index 00000000000..cc4f1efe012 --- /dev/null +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/BulkUpdateOrderResult.kt @@ -0,0 +1,16 @@ +package com.woocommerce.android.ui.orders.list + +sealed class BulkUpdateOrderResult { + data class PartialSuccess( + val successCount: Int, + val failureCount: Int + ) : BulkUpdateOrderResult() + + data object AllSuccess : BulkUpdateOrderResult() + + data object AllFailed : BulkUpdateOrderResult() + + data object NoOrdersUpdated : BulkUpdateOrderResult() + + data class Error(val exception: Exception) : BulkUpdateOrderResult() +} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListRepository.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListRepository.kt index 7f01a8b7449..ac06633a0bf 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListRepository.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListRepository.kt @@ -40,8 +40,6 @@ class OrderListRepository @Inject constructor( companion object { private const val TAG = "OrderListRepository" private const val ORDER_STATUS_TRASH = "trash" - private const val BULK_UPDATE_ORDER_STATUS_ALL_FAILED = "Unable to update any orders." - private const val BULK_UPDATE_ORDER_NOTHING_UPDATED = "No orders were updated." private const val BULK_UPDATE_ORDER_NO_RESPONSE = "No response received." } @@ -181,7 +179,7 @@ class OrderListRepository @Inject constructor( } } - suspend fun bulkUpdateOrderStatus(orderIds: List, newStatus: Order.Status): Result { + suspend fun bulkUpdateOrderStatus(orderIds: List, newStatus: Order.Status): BulkUpdateOrderResult { val result = orderStore.batchUpdateOrdersStatus( site = selectedSite.get(), orderIds = orderIds, @@ -190,25 +188,23 @@ class OrderListRepository @Inject constructor( return if (result.isError) { WooLog.e(ORDERS, "Error bulk updating order status: ${result.error.message}") - Result.failure(WooException(result.error)) + BulkUpdateOrderResult.Error(WooException(result.error)) } else { result.model?.let { logBulkOrderUpdateResults(it) - // We want to return success if at least one order was updated. - // However, if: - // - there's no updated orders but there are failed orders, return failure - // - there's no updated orders and no failed orders, return failure when { - it.failedOrders.isNotEmpty() && it.updatedOrders.isEmpty() -> - Result.failure(Exception(BULK_UPDATE_ORDER_STATUS_ALL_FAILED)) - - it.failedOrders.isEmpty() && it.updatedOrders.isEmpty() -> - Result.failure(Exception(BULK_UPDATE_ORDER_NOTHING_UPDATED)) - - else -> Result.success(Unit) + it.failedOrders.isNotEmpty() && it.updatedOrders.isEmpty() -> BulkUpdateOrderResult.AllFailed + it.failedOrders.isEmpty() && it.updatedOrders.isEmpty() -> BulkUpdateOrderResult.NoOrdersUpdated + it.failedOrders.isNotEmpty() && it.updatedOrders.isNotEmpty() -> + BulkUpdateOrderResult.PartialSuccess( + successCount = it.updatedOrders.size, + failureCount = it.failedOrders.size + ) + + else -> BulkUpdateOrderResult.AllSuccess } - } ?: Result.failure(Exception(BULK_UPDATE_ORDER_NO_RESPONSE)) + } ?: BulkUpdateOrderResult.Error(Exception(BULK_UPDATE_ORDER_NO_RESPONSE)) } } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt index 7fe0797988e..d35138d82e0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/list/OrderListViewModel.kt @@ -230,6 +230,7 @@ class OrderListViewModel @Inject constructor( fun isSelecting() = viewState.orderListState == ViewState.OrderListState.Selecting private var isQueueingBulkUpdateSuccessMessage = false + private var bulkUpdateSuccessMessage = "" init { lifecycleRegistry.currentState = Lifecycle.State.CREATED @@ -484,7 +485,7 @@ class OrderListViewModel @Inject constructor( pagedListWrapper.data.distinct().observe(this) { if (isQueueingBulkUpdateSuccessMessage) { isQueueingBulkUpdateSuccessMessage = false - triggerEvent(Event.ShowSnackbar(R.string.orderlist_bulk_update_status_updated)) + triggerEvent(OrderListEvent.ShowSnackbarString(bulkUpdateSuccessMessage)) } } @@ -1002,21 +1003,7 @@ class OrderListViewModel @Inject constructor( newStatus = newStatus ) - if (result.isFailure) { - viewState = viewState.copy(isBulkUpdating = false) - trackBulkOrderUpdateFailure() - triggerEvent(Event.ShowSnackbar(R.string.error_generic)) - } else { - isQueueingBulkUpdateSuccessMessage = true - ordersPagedListWrapper?.fetchFirstPage() - - analyticsTracker.track( - AnalyticsEvent.ORDERS_LIST_BULK_UPDATE_SUCCESS, - mapOf( - AnalyticsTracker.KEY_PROPERTY to AnalyticsTracker.VALUE_STATUS, - ) - ) - } + handleBulkUpdateResult(result) } } } else { @@ -1026,6 +1013,55 @@ class OrderListViewModel @Inject constructor( exitSelectionMode() } + private fun handleBulkUpdateResult(result: BulkUpdateOrderResult) { + when (result) { + is BulkUpdateOrderResult.AllSuccess, + is BulkUpdateOrderResult.PartialSuccess -> { + isQueueingBulkUpdateSuccessMessage = true + bulkUpdateSuccessMessage = when (result) { + is BulkUpdateOrderResult.AllSuccess -> resourceProvider.getString( + R.string.orderlist_bulk_update_status_updated + ) + + is BulkUpdateOrderResult.PartialSuccess -> resourceProvider.getString( + R.string.orderlist_bulk_update_result_partial_success, + result.successCount, + result.failureCount + ) + + else -> resourceProvider.getString(R.string.orderlist_bulk_update_status_updated) + } + ordersPagedListWrapper?.fetchFirstPage() + trackBulkOrderUpdateSuccess() + } + + is BulkUpdateOrderResult.NoOrdersUpdated, + is BulkUpdateOrderResult.AllFailed, + is BulkUpdateOrderResult.Error -> { + viewState = viewState.copy(isBulkUpdating = false) + trackBulkOrderUpdateFailure() + val messageRes = when (result) { + is BulkUpdateOrderResult.NoOrdersUpdated -> + R.string.orderlist_bulk_update_result_no_orders_updated + + is BulkUpdateOrderResult.AllFailed -> R.string.orderlist_bulk_update_result_all_failed + is BulkUpdateOrderResult.Error -> R.string.error_generic + else -> R.string.error_generic + } + triggerEvent(Event.ShowSnackbar(messageRes)) + } + } + } + + private fun trackBulkOrderUpdateSuccess() { + analyticsTracker.track( + AnalyticsEvent.ORDERS_LIST_BULK_UPDATE_SUCCESS, + mapOf( + AnalyticsTracker.KEY_PROPERTY to AnalyticsTracker.VALUE_STATUS, + ) + ) + } + private fun trackBulkOrderUpdateFailure() { analyticsTracker.track( AnalyticsEvent.ORDERS_LIST_BULK_UPDATE_FAILURE, diff --git a/WooCommerce/src/main/res/values/strings.xml b/WooCommerce/src/main/res/values/strings.xml index 8cc104203e8..1b2991e8a2a 100644 --- a/WooCommerce/src/main/res/values/strings.xml +++ b/WooCommerce/src/main/res/values/strings.xml @@ -619,6 +619,9 @@ Update status Status updated! Maximum selection count (%d) is reached. + No orders updated. Please try again. + Failed to update orders. Please try again. + (%d) orders updated, but (%d) orders failed to update. Please try again.