Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.woocommerce.android.ui.woopos.common.data

import com.woocommerce.android.model.Order
import com.woocommerce.android.model.Refund
import com.woocommerce.android.model.toAppModel
import com.woocommerce.android.tools.SelectedSite
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.wordpress.android.fluxc.store.WCRefundStore
import java.math.BigDecimal
import javax.inject.Inject

class WooPosRetrieveOrderRefunds @Inject constructor(
private val refundStore: WCRefundStore,
private val selectedSite: SelectedSite
) {
suspend operator fun invoke(order: Order): Result<List<Refund>> =
withContext(Dispatchers.IO) {
if (order.refundTotal.compareTo(BigDecimal.ZERO) == 0) {
return@withContext Result.success(emptyList())
}

val site = selectedSite.get()

var refundModels = refundStore.getAllRefunds(site, order.id)
if (refundModels.isEmpty()) {
val fetchResult = refundStore.fetchAllRefunds(site, order.id)
if (fetchResult.isError) {
return@withContext Result.failure(
Exception("Failed to fetch refunds: ${fetchResult.error.message}")
)
}
refundModels = fetchResult.model ?: emptyList()
}

Result.success(refundModels.map { it.toAppModel() })
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package com.woocommerce.android.ui.woopos.orders

import com.woocommerce.android.model.Order
import com.woocommerce.android.model.OrderMapper
import com.woocommerce.android.model.Refund
import com.woocommerce.android.tools.SelectedSite
import com.woocommerce.android.ui.woopos.common.data.WooPosRetrieveOrderRefunds
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.withContext
Expand All @@ -16,21 +21,27 @@ import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject

sealed class LoadOrdersResult {
data class SuccessCache(val orders: List<Order>) : LoadOrdersResult()
data class SuccessRemote(val orders: List<Order>) : LoadOrdersResult()
data class SuccessCache(val ordersWithRefunds: Map<Order, RefundFetchResult>) : LoadOrdersResult()
data class SuccessRemote(val ordersWithRefunds: Map<Order, RefundFetchResult>) : LoadOrdersResult()
data class Error(val message: String) : LoadOrdersResult()
}

sealed class SearchOrdersResult {
data class Success(val orders: List<Order>) : SearchOrdersResult()
data class Success(val ordersWithRefunds: Map<Order, RefundFetchResult>) : SearchOrdersResult()
data class Error(val message: String) : SearchOrdersResult()
}

sealed class RefundFetchResult {
data class Success(val refunds: List<Refund>) : RefundFetchResult()
object Error : RefundFetchResult()
}

class WooPosOrdersDataSource @Inject constructor(
private val restClient: OrderRestClient,
private val selectedSite: SelectedSite,
private val orderMapper: OrderMapper,
private val ordersCache: WooPosOrdersInMemoryCache
private val ordersCache: WooPosOrdersInMemoryCache,
private val retrieveOrderRefunds: WooPosRetrieveOrderRefunds
) {
private val canLoadMore = AtomicBoolean(false)
private val page = AtomicInteger(1)
Expand All @@ -45,12 +56,16 @@ class WooPosOrdersDataSource @Inject constructor(

fun loadOrders(): Flow<LoadOrdersResult> = flow {
val cached = ordersCache.getAll()
if (cached.isNotEmpty()) emit(LoadOrdersResult.SuccessCache(cached))
if (cached.isNotEmpty()) {
val cachedWithRefunds = fetchRefundsForOrders(cached)
emit(LoadOrdersResult.SuccessCache(cachedWithRefunds))
}

val result = loadFirstPage()
result.onSuccess {
ordersCache.setAll(it)
emit(LoadOrdersResult.SuccessRemote(it))
result.onSuccess { orders ->
ordersCache.setAll(orders)
val ordersWithRefunds = fetchRefundsForOrders(orders)
emit(LoadOrdersResult.SuccessRemote(ordersWithRefunds))
}.onFailure {
emit(LoadOrdersResult.Error(it.message ?: UNKNOWN_ERROR))
}
Expand All @@ -59,13 +74,20 @@ class WooPosOrdersDataSource @Inject constructor(
suspend fun searchOrders(searchQuery: String): SearchOrdersResult {
val result = loadFirstPage(searchQuery)
return result.fold(
onSuccess = { SearchOrdersResult.Success(it) },
onSuccess = { orders ->
val ordersWithRefunds = fetchRefundsForOrders(orders)
SearchOrdersResult.Success(ordersWithRefunds)
},
onFailure = { SearchOrdersResult.Error(it.message ?: UNKNOWN_ERROR) }
)
}

suspend fun loadMore(searchQuery: String? = null): Result<List<Order>> =
withContext(Dispatchers.IO) { loadNextPage(searchQuery) }
suspend fun loadMore(searchQuery: String? = null): Result<Map<Order, RefundFetchResult>> =
withContext(Dispatchers.IO) {
loadNextPage(searchQuery).map { orders ->
fetchRefundsForOrders(orders)
}
}

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

private fun WCOrderStore.OrderError.toThrowable(): Throwable =
Throwable("[$type] $message")

private suspend fun fetchRefundsForOrders(orders: List<Order>): Map<Order, RefundFetchResult> =
coroutineScope {
orders.map { order ->
async {
retrieveOrderRefunds(order).fold(
onSuccess = { refunds -> order to RefundFetchResult.Success(refunds) },
onFailure = { order to RefundFetchResult.Error }
)
}
}.awaitAll().toMap()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTyp
@Composable
fun WooPosOrderDetails(
modifier: Modifier = Modifier,
details: OrderDetailsViewState,
details: OrderDetailsViewState.Computed.Details,
onEmailReceiptButtonClicked: (Long) -> Unit
) {
Column(
Expand Down Expand Up @@ -89,7 +89,7 @@ fun WooPosOrderDetails(
}

@Composable
private fun OrdersHeader(details: OrderDetailsViewState) {
private fun OrdersHeader(details: OrderDetailsViewState.Computed.Details) {
Column(modifier = Modifier.fillMaxWidth()) {
WooPosText(
text = details.dateTime,
Expand All @@ -113,7 +113,7 @@ private fun OrdersHeader(details: OrderDetailsViewState) {
}

@Composable
private fun OrdersProducts(lineItems: List<OrderDetailsViewState.LineItemRow>) {
private fun OrdersProducts(lineItems: List<OrderDetailsViewState.Computed.Details.LineItemRow>) {
WooPosCard(shadowType = ShadowType.Soft) {
Column(Modifier.padding(WooPosSpacing.Medium.value)) {
WooPosText(
Expand All @@ -137,7 +137,7 @@ private fun OrdersProducts(lineItems: List<OrderDetailsViewState.LineItemRow>) {

@Composable
@Suppress("DestructuringDeclarationWithTooManyEntries")
private fun OrderProductItem(row: OrderDetailsViewState.LineItemRow) {
private fun OrderProductItem(row: OrderDetailsViewState.Computed.Details.LineItemRow) {
ConstraintLayout(
modifier = Modifier
.fillMaxWidth()
Expand Down Expand Up @@ -170,7 +170,7 @@ private fun OrderProductItem(row: OrderDetailsViewState.LineItemRow) {
style = WooPosTypography.BodyMedium,
color = WooPosTheme.colors.onSurfaceVariantHighest,
modifier = Modifier.constrainAs(qtyText) {
bottom.linkTo(image.bottom)
top.linkTo(nameText.bottom, margin = WooPosSpacing.XSmall.value)
start.linkTo(nameText.start)
end.linkTo(totalText.start, margin = WooPosSpacing.Small.value)
width = Dimension.fillToConstraints
Expand All @@ -189,7 +189,7 @@ private fun OrderProductItem(row: OrderDetailsViewState.LineItemRow) {
}

@Composable
private fun OrdersTotals(details: OrderDetailsViewState) {
private fun OrdersTotals(details: OrderDetailsViewState.Computed.Details) {
WooPosCard(shadowType = ShadowType.Soft) {
Column(Modifier.padding(WooPosSpacing.Medium.value)) {
WooPosText(
Expand Down Expand Up @@ -348,18 +348,25 @@ private fun DividerWithSpacing() {
@WooPosPreview
@Composable
fun WooPosOrderDetailsPreview() {
val orderDetails = OrderDetailsViewState(
val orderDetails = OrderDetailsViewState.Computed.Details(
id = 1L,
number = "#014",
dateTime = "Aug 28, 2025 at 10:31 AM",
customerEmail = "[email protected]",
status = PosOrderStatus(text = "Completed", colorKey = OrderStatusColorKey.COMPLETED),
lineItems = listOf(
OrderDetailsViewState.LineItemRow(101, "Cup", "2 x $4.00", "$8.00", null),
OrderDetailsViewState.LineItemRow(102, "Coffee Container", "1 x $10.00", "$10.00", null),
OrderDetailsViewState.LineItemRow(103, "Paper Filter", "1 x $5.00", "$5.00", null)
OrderDetailsViewState.Computed.Details.LineItemRow(101, "Cup", "2 x $4.00", "$8.00", null),
OrderDetailsViewState.Computed.Details.LineItemRow(102, "Coffee Container", "1 x $10.00", "$10.00", null),
OrderDetailsViewState.Computed.Details.LineItemRow(
103,
"A vey tasty coffee that incidentally has a very long name " +
"and should go over a few lines without overlapping anything",
"1 x $5.00",
"$5.00",
null
)
),
breakdown = OrderDetailsViewState.TotalsBreakdown(
breakdown = OrderDetailsViewState.Computed.Details.TotalsBreakdown(
products = "$23.00",
discount = "-$5.00",
discountCode = "SAVE5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fun WooPosOrdersLoadingState() {
modifier = Modifier
.weight(0.3f)
.fillMaxHeight()
.background(MaterialTheme.colorScheme.surface)
.background(MaterialTheme.colorScheme.surfaceBright)
.padding(top = WOO_POS_ORDERS_TOOLBAR_HEIGHT)
.padding(top = WooPosSpacing.XLarge.value)
)
Expand All @@ -54,7 +54,7 @@ fun WooPosOrdersLoadingState() {
modifier = Modifier
.weight(0.7f)
.fillMaxHeight()
.background(MaterialTheme.colorScheme.surfaceContainerLow)
.background(MaterialTheme.colorScheme.surface)
.padding(top = WooPosSpacing.Large.value)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ fun WooPosOrdersScreenPreview() {
state = WooPosOrdersState.Content(
items = WooPosOrdersState.Content.Items.Loaded(
items = mapOf(
item1 to details1,
item2 to details2
item1 to OrderDetailsViewState.Computed(orderId = 1L, details = details1),
item2 to OrderDetailsViewState.Computed(orderId = 2L, details = details2)
)
),
pullToRefreshState = WooPosPullToRefreshState.Enabled,
Expand Down Expand Up @@ -617,18 +617,18 @@ fun WooPosOrdersNothingFoundStatePreview() {
private fun sampleOrderDetails(
id: Long = 1L,
number: String = "#014"
) = OrderDetailsViewState(
) = OrderDetailsViewState.Computed.Details(
id = id,
number = number,
dateTime = "Aug 28, 2025 at 10:31 AM",
customerEmail = "[email protected]",
status = PosOrderStatus(text = "Completed", colorKey = OrderStatusColorKey.COMPLETED),
lineItems = listOf(
OrderDetailsViewState.LineItemRow(101, "Cup", "1 x $8.50", "$15.00", null),
OrderDetailsViewState.LineItemRow(102, "Coffee Container", "1 x $10.00", "$8.00", null),
OrderDetailsViewState.LineItemRow(103, "Paper Filter", "1 x $4.50", "$8.00", null)
OrderDetailsViewState.Computed.Details.LineItemRow(101, "Cup", "1 x $8.50", "$15.00", null),
OrderDetailsViewState.Computed.Details.LineItemRow(102, "Coffee Container", "1 x $10.00", "$8.00", null),
OrderDetailsViewState.Computed.Details.LineItemRow(103, "Paper Filter", "1 x $4.50", "$8.00", null)
),
breakdown = OrderDetailsViewState.TotalsBreakdown(
breakdown = OrderDetailsViewState.Computed.Details.TotalsBreakdown(
products = "$23.00",
discount = "-$5.00",
discountCode = "8qew4mnq",
Expand Down
Loading
Loading