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
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.woocommerce.android.ui.woopos.common.data

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 javax.inject.Inject

class WooPosGetOrderRefundsByOrderId @Inject constructor(
private val refundStore: WCRefundStore,
private val selectedSite: SelectedSite
) {
suspend operator fun invoke(orderId: Long): List<Refund> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider to add tests to this one if necessary

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

8b8420a

return withContext(Dispatchers.IO) {
refundStore.getAllRefunds(selectedSite.get(), orderId)
.map { it.toAppModel() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.woocommerce.android.R
import com.woocommerce.android.ui.woopos.common.composeui.WooPosPreview
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosButton
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosCard
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosText
Expand All @@ -42,7 +43,7 @@ import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosThe
import com.woocommerce.android.ui.woopos.common.composeui.designsystem.WooPosTypography

@Composable
fun OrderDetails(
fun WooPosOrderDetails(
modifier: Modifier = Modifier,
details: OrderDetailsViewState,
onEmailReceiptButtonClicked: (Long) -> Unit = {}
Expand Down Expand Up @@ -227,28 +228,73 @@ fun OrderDetails(
fontWeight = FontWeight.Bold
)
}
}
}

Column {
Row(Modifier.fillMaxWidth()) {
WooPosText(
text = stringResource(R.string.woopos_orders_details_total_paid_label),
style = WooPosTypography.BodySmall,
modifier = Modifier.weight(1f)
)
WooPosText(
text = details.totalPaid,
style = WooPosTypography.BodySmall
)
}
details.paymentMethodTitle?.let {
Spacer(Modifier.height(WooPosSpacing.XSmall.value))
WooPosText(
text = it,
style = WooPosTypography.BodySmall,
color = WooPosTheme.colors.onSurfaceVariantHighest
)
Row(
Modifier
.fillMaxWidth()
) {
WooPosText(
text = stringResource(R.string.woopos_orders_details_total_paid_label),
style = WooPosTypography.BodySmall,
modifier = Modifier.weight(1f)
)
WooPosText(
text = details.totalPaid,
style = WooPosTypography.BodySmall
)
}
details.paymentMethodTitle?.let {
Spacer(Modifier.height(WooPosSpacing.XSmall.value))
WooPosText(
text = it,
style = WooPosTypography.BodySmall,
color = WooPosTheme.colors.onSurfaceVariantHighest,
)
}

if (details.breakdown.refunds.isNotEmpty()) {
Spacer(Modifier.height(WooPosSpacing.Small.value))
details.breakdown.refunds.forEachIndexed { index, refundAmount ->
Row(
Modifier
.fillMaxWidth()
) {
WooPosText(
text = stringResource(R.string.woopos_orders_details_refunded_label),
style = WooPosTypography.BodySmall,
modifier = Modifier.weight(1f)
)
WooPosText(
text = refundAmount,
style = WooPosTypography.BodySmall
)
}
if (index < details.breakdown.refunds.size - 1) {
Spacer(Modifier.height(WooPosSpacing.XSmall.value))
}
}
}

details.breakdown.netPayment?.let { netPayment ->
Spacer(Modifier.height(WooPosSpacing.Small.value))
Row(
Modifier
.fillMaxWidth()
.padding(bottom = WooPosSpacing.Medium.value)
) {
WooPosText(
text = stringResource(R.string.woopos_orders_details_net_payment_label),
style = WooPosTypography.BodySmall,
fontWeight = FontWeight.Bold,
modifier = Modifier.weight(1f)
)
WooPosText(
text = netPayment,
style = WooPosTypography.BodySmall,
fontWeight = FontWeight.Bold
)
}
}
}
}
}
Expand Down Expand Up @@ -281,3 +327,39 @@ private fun OrderLineItemImage(imageUrl: String?) {
)
}
}

@WooPosPreview
@Composable
fun WooPosOrderDetailsPreview() {
val orderDetails = OrderDetailsViewState(
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", "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)
),
breakdown = OrderDetailsViewState.TotalsBreakdown(
products = "$23.00",
discount = "-$5.00",
discountCode = "8qew4mnq",
taxes = "$0.00",
shipping = null,
refunds = listOf("-$3.00", "-$2.00"),
netPayment = "$12.00"
),
total = "$17.00",
totalPaid = "$17.00",
paymentMethodTitle = "WooCommerce In-Person Payments"
)

WooPosTheme {
WooPosOrderDetails(
details = orderDetails,
onEmailReceiptButtonClicked = {}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
Expand Down Expand Up @@ -167,7 +166,7 @@ private fun OrdersContent(
.background(MaterialTheme.colorScheme.surface)
)

OrderDetails(
WooPosOrderDetails(
modifier = Modifier
.weight(0.7f)
.fillMaxHeight()
Expand Down Expand Up @@ -517,7 +516,9 @@ private fun sampleOrderDetails(
discount = "-$5.00",
discountCode = "8qew4mnq",
taxes = "$0.00",
shipping = null
shipping = null,
refunds = listOf("-$3.00", "-$2.00"),
netPayment = "$12.00"
),
total = "$17.00",
totalPaid = "$17.00",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ data class OrderDetailsViewState(
val discount: String?,
val discountCode: String?,
val taxes: String,
val shipping: String?
val shipping: String?,
val refunds: List<String>,
val netPayment: String?
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.woocommerce.android.R
import com.woocommerce.android.model.Order
import com.woocommerce.android.tools.SelectedSite
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosSearchInputState
import com.woocommerce.android.ui.woopos.common.composeui.component.WooPosSearchUIEvent
import com.woocommerce.android.ui.woopos.common.data.WooPosGetOrderRefundsByOrderId
import com.woocommerce.android.ui.woopos.common.data.WooPosGetProductById
import com.woocommerce.android.ui.woopos.home.items.WooPosPaginationState
import com.woocommerce.android.ui.woopos.home.items.WooPosPullToRefreshState
import com.woocommerce.android.ui.woopos.util.ext.formatToMMMddYYYYAtHHmm
import com.woocommerce.android.ui.woopos.util.format.WooPosFormatPrice
import com.woocommerce.android.viewmodel.ResourceProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
Expand All @@ -19,19 +20,18 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.wordpress.android.fluxc.store.WooCommerceStore
import java.math.BigDecimal
import java.util.Locale
import javax.inject.Inject

@HiltViewModel
class WooPosOrdersViewModel @Inject constructor(
private val ordersDataSource: WooPosOrdersDataSource,
private val wooCommerceStore: WooCommerceStore,
private val selectedSite: SelectedSite,
private val resourceProvider: ResourceProvider,
private val locale: Locale,
private val getProductById: WooPosGetProductById,
private val formatPrice: WooPosFormatPrice,
private val getOrderRefunds: WooPosGetOrderRefundsByOrderId,
) : ViewModel() {

private val _state = MutableStateFlow<WooPosOrdersState>(
Expand Down Expand Up @@ -326,14 +326,7 @@ class WooPosOrdersViewModel @Inject constructor(
}
}

private fun mapOrderItem(order: Order, selectedId: Long?): OrderItemViewState {
val formattedOrderTotals = wooCommerceStore.formatCurrencyForDisplay(
amount = order.total.toDouble(),
site = selectedSite.get(),
currencyCode = null,
applyDecimalFormatting = true
)

private suspend fun mapOrderItem(order: Order, selectedId: Long?): OrderItemViewState {
val statusText = order.status.localizedLabel(resourceProvider, locale)

return OrderItemViewState(
Expand All @@ -342,7 +335,7 @@ class WooPosOrdersViewModel @Inject constructor(
date = order.dateCreated.formatToMMMddYYYYAtHHmm(
atWord = resourceProvider.getString(R.string.date_time_connector)
),
total = formattedOrderTotals,
total = formatPrice(order.total),
customerEmail = order.customer?.email,
isSelected = order.id == selectedId,
status = PosOrderStatus(
Expand All @@ -353,13 +346,6 @@ class WooPosOrdersViewModel @Inject constructor(
}

private suspend fun mapOrderDetails(order: Order): OrderDetailsViewState {
fun fmt(amount: BigDecimal) = wooCommerceStore.formatCurrencyForDisplay(
amount = amount.toDouble(),
site = selectedSite.get(),
currencyCode = null,
applyDecimalFormatting = true
)

val statusText = order.status.localizedLabel(resourceProvider, locale)

val status = PosOrderStatus(
Expand All @@ -373,19 +359,31 @@ class WooPosOrdersViewModel @Inject constructor(
OrderDetailsViewState.LineItemRow(
id = item.itemId,
name = item.name,
qtyAndUnitPrice = "${item.quantity.toInt()} x ${fmt(unitPrice)}",
lineTotal = fmt(item.total),
qtyAndUnitPrice = "${item.quantity.toInt()} x ${formatPrice(unitPrice)}",
lineTotal = formatPrice(item.total),
imageUrl = product?.firstImageUrl
)
}

val discountCode = order.couponLines.firstOrNull()?.code

val refunds = getOrderRefunds(order.id)
val refundAmounts = refunds.map { "-${formatPrice(it.amount)}" }
val totalRefunded = refunds.sumOf { it.amount }
val netPayment = if (totalRefunded > BigDecimal.ZERO) {
formatPrice(order.total - totalRefunded)
} else {
null
}

val breakdown = OrderDetailsViewState.TotalsBreakdown(
products = fmt(order.productsTotal),
discount = order.discountTotal.takeIf { it != BigDecimal.ZERO }?.let { "-${fmt(it)}" },
products = formatPrice(order.productsTotal),
discount = order.discountTotal.takeIf { it != BigDecimal.ZERO }?.let { "-${formatPrice(it)}" },
discountCode = discountCode,
taxes = fmt(order.totalTax),
shipping = order.shippingTotal.takeIf { it != BigDecimal.ZERO }?.let { fmt(it) }
taxes = formatPrice(order.totalTax),
shipping = order.shippingTotal.takeIf { it != BigDecimal.ZERO }?.let { formatPrice(it) },
refunds = refundAmounts,
netPayment = netPayment
)

return OrderDetailsViewState(
Expand All @@ -398,8 +396,8 @@ class WooPosOrdersViewModel @Inject constructor(
status = status,
lineItems = lineItems,
breakdown = breakdown,
total = fmt(order.total),
totalPaid = fmt(order.total),
total = formatPrice(order.total),
totalPaid = formatPrice(order.total),
paymentMethodTitle = order.paymentMethodTitle.takeIf { it.isNotBlank() }
)
}
Expand Down
2 changes: 2 additions & 0 deletions WooCommerce/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3809,6 +3809,8 @@
<string name="woopos_orders_details_breakdown_shipping_label">Shipping</string>
<string name="woopos_orders_details_total_label">Total</string>
<string name="woopos_orders_details_total_paid_label">Total paid</string>
<string name="woopos_orders_details_refunded_label">Refunded</string>
<string name="woopos_orders_details_net_payment_label">Net Payment</string>
<string name="woopos_orders_details_products_list_content_description">Order products list</string>
<string name="woopos_orders_details_totals_card_content_description">Order totals breakdown</string>

Expand Down
Loading