Skip to content

[WOOMOB-2450][POS Refunds: M3] Add refund details dialog to POS order details#15502

Merged
samiuelson merged 15 commits intotrunkfrom
woomob-2450-woo-posrefuds-milestone-3-details-of-historical-refunds
Mar 11, 2026
Merged

[WOOMOB-2450][POS Refunds: M3] Add refund details dialog to POS order details#15502
samiuelson merged 15 commits intotrunkfrom
woomob-2450-woo-posrefuds-milestone-3-details-of-historical-refunds

Conversation

@samiuelson
Copy link
Copy Markdown
Contributor

@samiuelson samiuelson commented Mar 9, 2026

Description

Fixes WOOMOB-2450

When a refund row is tapped in the POS order details Totals section, a dialog now shows the refund's breakdown: refunded items with images, quantities and prices, items subtotal, tax, refund total, and payment method.

Changes:

  • Expand refund rows in Totals to show date, reason, and a "View details" link
  • Add RefundRow data class and RefundDetails dialog state
  • Enrich RefundInfo with per-refund metadata (label, date, reason, full Refund object)
  • Create WooPosRefundDetailsDialog composable using WooPosDialogWrapper
  • Wire dialog through ViewModel with proper state management
  • Refunds are enumerated from oldest to newest

Test Steps

  1. Open a POS order that has one or more refunds
  2. Scroll to the Totals section — verify each refund row shows: "Refund #N" with amount, date, optional reason, and "View details" link
  3. Tap anywhere on a refund row — verify the refund details dialog opens
  4. In the dialog, verify: title matches "Refund #N", refunded items are listed with images/names/qty/prices, items subtotal, tax, refund total, and payment method are shown
  5. Tap the X button or outside the dialog — verify it dismisses

Images/gif

image image
  • I have considered if this change warrants release notes and have added them to RELEASE-NOTES.txt if necessary. Use the "[Internal]" label for non-user-facing changes.

Replace the simple List<String> refund amounts in TotalsBreakdown with a
structured RefundRow (label, amount, date, reason). Update RefundInfo to
carry RefundRowData preserving the full Refund object for dialog use.
Refunds are sorted oldest-first before numbering. Add RefundDetails
variant to DialogState and new string resources.
Add ViewRefundDetailsClicked UI event and handle it in the ViewModel by
building dialog state from the stored RefundRowData. Add
buildLineItemsForSingleRefund to the mapper so the dialog can show
per-refund item breakdown. Store current refund rows alongside the
selected order for quick dialog construction.
Introduce WooPosRefundDetailsDialog composable showing refunded items,
subtotal, tax, and total when "View details" is tapped. Update refund
rows in the totals section to display date, reason, and a clickable
"View details" link. Wire the dialog into WooPosOrdersScreen.
@samiuelson samiuelson added type: enhancement A request for an enhancement. feature: point of sale POS project labels Mar 9, 2026
@dangermattic
Copy link
Copy Markdown
Collaborator

dangermattic commented Mar 9, 2026

1 Warning
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Copy Markdown
Collaborator

wpmobilebot commented Mar 9, 2026

App Icon📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App NameWooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Build Number734
Version24.3-rc-3
Application IDcom.woocommerce.android.prealpha
Commit51b888c
Installation URL63r0v1apbvap8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 33.43653% with 215 lines in your changes missing coverage. Please review.
✅ Project coverage is 39.53%. Comparing base (9e92207) to head (51b888c).
⚠️ Report is 16 commits behind head on trunk.

Files with missing lines Patch % Lines
...orders/details/refund/WooPosRefundDetailsDialog.kt 0.00% 125 Missing ⚠️
...oid/ui/woopos/orders/details/WooPosOrderDetails.kt 0.00% 65 Missing ⚠️
.../android/ui/woopos/orders/WooPosOrdersViewModel.kt 76.47% 6 Missing and 10 partials ⚠️
...s/orders/details/refund/WooPosRefundInfoBuilder.kt 83.78% 5 Missing and 1 partial ⚠️
.../woopos/orders/details/WooPosOrderDetailsMapper.kt 70.00% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##              trunk   #15502      +/-   ##
============================================
- Coverage     39.54%   39.53%   -0.02%     
- Complexity    11237    11248      +11     
============================================
  Files          2251     2252       +1     
  Lines        129763   130058     +295     
  Branches      18170    18208      +38     
============================================
+ Hits          51318    51415      +97     
- Misses        73208    73395     +187     
- Partials       5237     5248      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@samiuelson samiuelson changed the title [WOOMOB-2450] Add refund details dialog to POS order details [WOOMOB-2450][POS Refunds: M3] Add refund details dialog to POS order details Mar 10, 2026
Center the title, make items list scrollable, update divider
thickness, and fix TotalRowLine to use consistent text styling.
Handle singular/plural forms correctly (e.g. "1 item" vs "2 items")
by switching to getQuantityString.
@samiuelson samiuelson added this to the 24.4 milestone Mar 10, 2026
@samiuelson samiuelson removed the type: enhancement A request for an enhancement. label Mar 10, 2026
@samiuelson samiuelson requested a review from Copilot March 10, 2026 12:02
@samiuelson samiuelson marked this pull request as ready for review March 10, 2026 12:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a refund details dialog to the POS order details screen, allowing users to tap on a refund row to view a breakdown that includes refunded items (with images, quantities, and prices), items subtotal, tax, refund total, and payment method. It is part of the M3 milestone for POS Refunds (WOOMOB-2450).

Changes:

  • Enriched RefundInfo/RefundRowData with per-refund metadata (label, date, reason, full Refund object) and updated TotalsBreakdown.refunds from List<String> to List<RefundRow>
  • Added WooPosRefundDetailsDialog composable and wired the new RefundDetails dialog state through ViewModel events (ViewRefundDetailsClicked) and screen-level handling
  • Added buildLineItemsForSingleRefund to WooPosOrderDetailsMapper and new state management fields (currentRefundRows, currentOrderForRefunds) in the ViewModel to support showing per-refund line items

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
WooPosRefundInfoBuilder.kt Builds RefundRowData per refund with label, date, reason, and amount; changed error handling
WooPosOrderDetailsMapper.kt Added buildLineItemsForSingleRefund for building line items for a single refund
WooPosOrdersState.kt Added RefundRow data class and RefundDetails dialog state
WooPosOrdersUIEvent.kt Added ViewRefundDetailsClicked UI event
WooPosOrdersViewModel.kt Added state management for refund details dialog; new currentRefundRows/currentOrderForRefunds fields
WooPosOrderDetails.kt Refund rows now show label, date, reason, and a "View details" link; whole row is tappable
WooPosRefundDetailsDialog.kt New dialog composable displaying refund item breakdown
WooPosOrdersScreen.kt Wired new RefundDetails dialog state into screen rendering
strings.xml Added string resources for refund label, tax, total, subtotal plurals, and dialog background
WooPosOrderDetailsMapperTest.kt Updated mock for renamed RefundInfo constructor parameter
WooPosOrdersViewModelTest.kt Added formatPrice dependency and updated refund row assertions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@samiuelson samiuelson requested a review from malinajirka March 10, 2026 13:31
@malinajirka malinajirka self-assigned this Mar 11, 2026
Copy link
Copy Markdown
Contributor

@malinajirka malinajirka left a comment

Choose a reason for hiding this comment

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

Thanks @samiuelson! I haven't found anything critical, but a couple things worth considering.

  1. The bottom padding of the last item in the list is always smaller - notice the space between the product image and divider below it is different between the first and second items.
Image
  1. It is very easy to miss that the content is scrollable - I'd consider adding a shadow on top of the Totals section when there is a scroll. We use the same pattern for example in the cart. (P.S. I noticed the same issue in the process refund dialog)
Screenshot 2026-03-11 at 8 18 16
  1. The centered title feels a bit off - the designs show it centered to the left.
Screenshot 2026-03-11 at 8 21 05

emptyList()
}
RefundInfo(amounts, BigDecimal.ZERO)
RefundInfo(emptyList(), BigDecimal.ZERO)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

❓ Seems like previously we showed an error when we failed to load refunds, but now we ignore the error. Is this an intentional change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — this was unintentional. Restored showing the inline error in a86b94d

private var loadingMoreOrdersJob: Job? = null
private var sideLoadActionsJob: Job? = null

private var currentRefundRows: List<RefundRowData> = emptyList()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📓 I technically don't see any bug with this approach, but considering we have one VM for everything, with no actual encapsulation (just to be clear, this wasn't introduced in this or previous PR, but over time), I'm worried having multiple independent states that can easily get out of sync is quite risky. Could we somehow make this state dependent on the currently selected order to ensure we don't display refunds for a different order with future code changes? (not necessarily in this PR, but as an maintainability improvement)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, having those as independent var fields was fragile. Consolidated currentRefundRows and currentOrderForRefunds into a single CachedRefundData(orderId, rows, order) data class so they can't drift apart → 9162519

val refundTotal = formatPrice(rowData.refund.amount, order.currency)

val updatedState = _state.value as? WooPosOrdersState.Content ?: return@launch
_state.value = updatedState.copy(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 I'd consider adding a check if still the same order is selected - the coroutine might take a while to start and complete.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good idea — added here → 2ed4282

Add refundLoadError field to RefundInfo and TotalsBreakdown so the UI
can display an inline error message when fetching refunds fails, instead
of silently returning empty data.
Replace independent currentRefundRows and currentOrderForRefunds fields
with a single CachedRefundData data class that ties the orderId, refund
rows, and order together to prevent them from getting out of sync.
Verify the selected order still matches the cached refund data before
showing the refund details dialog, preventing stale data from appearing
if the user navigated to a different order while the coroutine ran.
@samiuelson
Copy link
Copy Markdown
Contributor Author

Thanks for review, Jirka!

  1. The bottom padding of the last item in the list is always smaller - notice the space between the product image and divider below it is different between the first and second items.
  1. It is very easy to miss that the content is scrollable - I'd consider adding a shadow on top of the Totals section when there is a scroll. We use the same pattern for example in the cart. (P.S. I noticed the same issue in the process refund dialog)

Both 1. and 2. were addressed in c8119fa

  1. The centered title feels a bit off - the designs show it centered to the left.
Screenshot 2026-03-11 at 8 21 05

This is intentional divergence from figma specs, suggested by @kidinov in past, to keep refund-specific dialogs consistent with other dialogs in POS.

@samiuelson samiuelson enabled auto-merge March 11, 2026 17:35
@samiuelson samiuelson merged commit a284699 into trunk Mar 11, 2026
16 checks passed
@samiuelson samiuelson deleted the woomob-2450-woo-posrefuds-milestone-3-details-of-historical-refunds branch March 11, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants