Skip to content

Commit 8834f98

Browse files
authored
Merge pull request #14915 from woocommerce/fix/pos-historical-orders-show-refunds-net-payment
[POS Orders] Fetch refunds remotely if not stored locally
2 parents 63aab94 + 76683f1 commit 8834f98

File tree

11 files changed

+487
-271
lines changed

11 files changed

+487
-271
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/common/data/WooPosGetOrderRefundsByOrderId.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.woocommerce.android.ui.woopos.common.data
2+
3+
import com.woocommerce.android.model.Order
4+
import com.woocommerce.android.model.Refund
5+
import com.woocommerce.android.model.toAppModel
6+
import com.woocommerce.android.tools.SelectedSite
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.withContext
9+
import org.wordpress.android.fluxc.store.WCRefundStore
10+
import java.math.BigDecimal
11+
import javax.inject.Inject
12+
13+
class WooPosRetrieveOrderRefunds @Inject constructor(
14+
private val refundStore: WCRefundStore,
15+
private val selectedSite: SelectedSite
16+
) {
17+
suspend operator fun invoke(order: Order): Result<List<Refund>> =
18+
withContext(Dispatchers.IO) {
19+
if (order.refundTotal.compareTo(BigDecimal.ZERO) == 0) {
20+
return@withContext Result.success(emptyList())
21+
}
22+
23+
val site = selectedSite.get()
24+
25+
var refundModels = refundStore.getAllRefunds(site, order.id)
26+
if (refundModels.isEmpty()) {
27+
val fetchResult = refundStore.fetchAllRefunds(site, order.id)
28+
if (fetchResult.isError) {
29+
return@withContext Result.failure(
30+
Exception("Failed to fetch refunds: ${fetchResult.error.message}")
31+
)
32+
}
33+
refundModels = fetchResult.model ?: emptyList()
34+
}
35+
36+
Result.success(refundModels.map { it.toAppModel() })
37+
}
38+
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersDataSource.kt

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ package com.woocommerce.android.ui.woopos.orders
22

33
import com.woocommerce.android.model.Order
44
import com.woocommerce.android.model.OrderMapper
5+
import com.woocommerce.android.model.Refund
56
import com.woocommerce.android.tools.SelectedSite
7+
import com.woocommerce.android.ui.woopos.common.data.WooPosRetrieveOrderRefunds
68
import kotlinx.coroutines.Dispatchers
9+
import kotlinx.coroutines.async
10+
import kotlinx.coroutines.awaitAll
11+
import kotlinx.coroutines.coroutineScope
712
import kotlinx.coroutines.flow.Flow
813
import kotlinx.coroutines.flow.flow
914
import kotlinx.coroutines.withContext
@@ -16,21 +21,27 @@ import java.util.concurrent.atomic.AtomicInteger
1621
import javax.inject.Inject
1722

1823
sealed class LoadOrdersResult {
19-
data class SuccessCache(val orders: List<Order>) : LoadOrdersResult()
20-
data class SuccessRemote(val orders: List<Order>) : LoadOrdersResult()
24+
data class SuccessCache(val ordersWithRefunds: Map<Order, RefundFetchResult>) : LoadOrdersResult()
25+
data class SuccessRemote(val ordersWithRefunds: Map<Order, RefundFetchResult>) : LoadOrdersResult()
2126
data class Error(val message: String) : LoadOrdersResult()
2227
}
2328

2429
sealed class SearchOrdersResult {
25-
data class Success(val orders: List<Order>) : SearchOrdersResult()
30+
data class Success(val ordersWithRefunds: Map<Order, RefundFetchResult>) : SearchOrdersResult()
2631
data class Error(val message: String) : SearchOrdersResult()
2732
}
2833

34+
sealed class RefundFetchResult {
35+
data class Success(val refunds: List<Refund>) : RefundFetchResult()
36+
object Error : RefundFetchResult()
37+
}
38+
2939
class WooPosOrdersDataSource @Inject constructor(
3040
private val restClient: OrderRestClient,
3141
private val selectedSite: SelectedSite,
3242
private val orderMapper: OrderMapper,
33-
private val ordersCache: WooPosOrdersInMemoryCache
43+
private val ordersCache: WooPosOrdersInMemoryCache,
44+
private val retrieveOrderRefunds: WooPosRetrieveOrderRefunds
3445
) {
3546
private val canLoadMore = AtomicBoolean(false)
3647
private val page = AtomicInteger(1)
@@ -45,12 +56,16 @@ class WooPosOrdersDataSource @Inject constructor(
4556

4657
fun loadOrders(): Flow<LoadOrdersResult> = flow {
4758
val cached = ordersCache.getAll()
48-
if (cached.isNotEmpty()) emit(LoadOrdersResult.SuccessCache(cached))
59+
if (cached.isNotEmpty()) {
60+
val cachedWithRefunds = fetchRefundsForOrders(cached)
61+
emit(LoadOrdersResult.SuccessCache(cachedWithRefunds))
62+
}
4963

5064
val result = loadFirstPage()
51-
result.onSuccess {
52-
ordersCache.setAll(it)
53-
emit(LoadOrdersResult.SuccessRemote(it))
65+
result.onSuccess { orders ->
66+
ordersCache.setAll(orders)
67+
val ordersWithRefunds = fetchRefundsForOrders(orders)
68+
emit(LoadOrdersResult.SuccessRemote(ordersWithRefunds))
5469
}.onFailure {
5570
emit(LoadOrdersResult.Error(it.message ?: UNKNOWN_ERROR))
5671
}
@@ -59,13 +74,20 @@ class WooPosOrdersDataSource @Inject constructor(
5974
suspend fun searchOrders(searchQuery: String): SearchOrdersResult {
6075
val result = loadFirstPage(searchQuery)
6176
return result.fold(
62-
onSuccess = { SearchOrdersResult.Success(it) },
77+
onSuccess = { orders ->
78+
val ordersWithRefunds = fetchRefundsForOrders(orders)
79+
SearchOrdersResult.Success(ordersWithRefunds)
80+
},
6381
onFailure = { SearchOrdersResult.Error(it.message ?: UNKNOWN_ERROR) }
6482
)
6583
}
6684

67-
suspend fun loadMore(searchQuery: String? = null): Result<List<Order>> =
68-
withContext(Dispatchers.IO) { loadNextPage(searchQuery) }
85+
suspend fun loadMore(searchQuery: String? = null): Result<Map<Order, RefundFetchResult>> =
86+
withContext(Dispatchers.IO) {
87+
loadNextPage(searchQuery).map { orders ->
88+
fetchRefundsForOrders(orders)
89+
}
90+
}
6991

7092
suspend fun refreshOrderById(orderId: Long): Result<Order> {
7193
val site = selectedSite.get()
@@ -135,4 +157,16 @@ class WooPosOrdersDataSource @Inject constructor(
135157

136158
private fun WCOrderStore.OrderError.toThrowable(): Throwable =
137159
Throwable("[$type] $message")
160+
161+
private suspend fun fetchRefundsForOrders(orders: List<Order>): Map<Order, RefundFetchResult> =
162+
coroutineScope {
163+
orders.map { order ->
164+
async {
165+
retrieveOrderRefunds(order).fold(
166+
onSuccess = { refunds -> order to RefundFetchResult.Success(refunds) },
167+
onFailure = { order to RefundFetchResult.Error }
168+
)
169+
}
170+
}.awaitAll().toMap()
171+
}
138172
}

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/orders/WooPosOrdersState.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ sealed class OrderDetailsViewState {
1414
@Immutable
1515
data class Lazy(
1616
override val orderId: Long,
17-
val order: Order
17+
val order: Order,
18+
val refundResult: RefundFetchResult
1819
) : OrderDetailsViewState()
1920

2021
@Immutable

0 commit comments

Comments
 (0)