Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Woo POS][Non-Simple Products] Remove null price check on Products and Variations screen #13312

Merged
merged 13 commits into from
Jan 16, 2025

Conversation

AnirudhBhat
Copy link
Contributor

@AnirudhBhat AnirudhBhat commented Jan 15, 2025

Closes: #13293

Description

This PR removes null price filtering we've had for some time on client side. Since we have decided to allow free products to be displayed on POS, we are allowing products whose price are not set to be allowed to display as well considering those to be free products.

Along with this, this PR also hides card payment screen on checkout if the cart items contain only free products.

discussion: p1736504688523299/1736484154.214279-slack-C070SJRA8DP

Steps to reproduce

Empty price

  1. Ensure you have products and variations whose price are not set (empty price)
  2. Navigate to POS (more menu -> POS)
  3. Ensure you see the product whose price is empty in the list
  4. Ensure you see the variation whose price is empty in the variations screen

Zero price

  1. Ensure you have products and variations whose price are set to zero
  2. Navigate to POS (more menu -> POS)
  3. Ensure you see the product whose price is zero in the list
  4. Ensure you see the variation whose price is zero in the variations screen

Checkout screen for free products

  1. Ensure you have products and variations whose price are set to zero
  2. Navigate to POS (more menu -> POS)
  3. Add product whose price is set to 0 to cart
  4. Click on checkout and navigate to checkout screen
  5. Ensure you don't see card payment UI here. Just the cash payment screen
  6. Ensure you can complete cash payment successfully

Checkout screen for non-free products

  1. Navigate to POS (more menu -> POS)
  2. Add product whose price is set to other than 0 to cart
  3. Click on checkout and navigate to checkout screen
  4. Ensure you see card payment UI along with the cash payment screen
  5. Ensure you can complete card payment successfully

The tests that have been performed

Tested the above scenarios

Images/gif

free_products.mp4
  • 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.

Reviewer (or Author, in the case of optional code reviews):

Please make sure these conditions are met before approving the PR, or request changes if the PR needs improvement:

  • The PR is small and has a clear, single focus, or a valid explanation is provided in the description. If needed, please request to split it into smaller PRs.
  • Ensure Adequate Unit Test Coverage: The changes are reasonably covered by unit tests or an explanation is provided in the PR description.
  • Manual Testing: The author listed all the tests they ran, including smoke tests when needed (e.g., for refactorings). The reviewer confirmed that the PR works as expected on big (tablet) and small (phone) in case of UI changes, and no regressions are added.

@AnirudhBhat AnirudhBhat added type: task An internally driven task. feature: point of sale POS project labels Jan 15, 2025
@AnirudhBhat AnirudhBhat added this to the 21.5 milestone Jan 15, 2025
# Conflicts:
#	WooCommerce/src/main/kotlin/com/woocommerce/android/ui/woopos/home/items/products/WooPosProductsDataSource.kt
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Jan 15, 2025

📲 You can test the changes from this Pull Request in WooCommerce-Wear Android by scanning the QR code below to install the corresponding build.
App Name WooCommerce-Wear Android
Platform⌚️ Wear OS
FlavorJalapeno
Build TypeDebug
Commita953166
Direct Downloadwoocommerce-wear-prototype-build-pr13312-a953166.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Jan 15, 2025

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

App Name WooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Commita953166
Direct Downloadwoocommerce-prototype-build-pr13312-a953166.apk

@codecov-commenter
Copy link

codecov-commenter commented Jan 15, 2025

Codecov Report

Attention: Patch coverage is 42.85714% with 4 lines in your changes missing coverage. Please review.

Project coverage is 41.09%. Comparing base (888b2e9) to head (a953166).
Report is 44 commits behind head on trunk.

Files with missing lines Patch % Lines
...os/home/items/products/WooPosProductsDataSource.kt 0.00% 0 Missing and 2 partials ⚠️
...ome/items/variations/WooPosVariationsDataSource.kt 0.00% 0 Missing and 1 partial ⚠️
...oid/ui/woopos/home/totals/WooPosTotalsViewModel.kt 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##              trunk   #13312      +/-   ##
============================================
- Coverage     41.10%   41.09%   -0.01%     
+ Complexity     6421     6417       -4     
============================================
  Files          1321     1321              
  Lines         77177    77176       -1     
  Branches      10643    10645       +2     
============================================
- Hits          31722    31718       -4     
  Misses        42646    42646              
- Partials       2809     2812       +3     

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

@samiuelson samiuelson self-assigned this Jan 15, 2025
Copy link
Collaborator

@samiuelson samiuelson left a comment

Choose a reason for hiding this comment

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

Works well, @AnirudhBhat! Please take a look at a few code improvement ideas I left.

@@ -12,6 +12,7 @@ sealed class WooPosTotalsViewState : Parcelable {
val orderTaxText: String,
val orderTotalText: String,
val readerStatus: ReaderStatus,
val isFreeOrder: Boolean,
Copy link
Collaborator

Choose a reason for hiding this comment

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

💡 The UI doesn’t really care if the order is free; it only cares whether the reader status is shown or hidden. The state model would be cleaner and more readable if, instead of adding an isFreeOrder property to WooPosTotalsViewState, we changed ReaderStatus to reflect when we don’t want it displayed.

For example, we could add a data object Hidden: ReaderStatus() subclass, rather than relying on WooPosTotalsViewState.isFreeOrder. This approach would also simplify the UI code. What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

💡 It would also be great to add a unit test for orders that include only free products.

Copy link
Contributor Author

@AnirudhBhat AnirudhBhat Jan 16, 2025

Choose a reason for hiding this comment

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

Thanks for the suggestion. I think this PR of yours already does this change. What do you think of making my change based on your PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After thinking more about this, I feel adding a new Hidden status to readerStatus field:

  1. Introduces complexity in managing a Hidden status, as it’s an artificial state not tied to the actual reader.
  2. Requires careful handling in the WooPosTotalsViewModel to ensure the Hidden status transitions correctly, especially when toggling between free orders and paid orders.
  3. Complicates UI logic to correctly display the cash payment screen when the card reader UI is hidden.

We could probably rename isFreeOrder into shouldShowReaderStatus. WDYT?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Feel free to take the approach you think is best 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would also be great to add a unit test for orders that include only free products.

Good suggestion! I've added it here

57c3d64

a953166

if (cardReaderFacade.readerStatus.value is Connected) {
if (
cardReaderFacade.readerStatus.value is Connected &&
dataState.value.orderTotal?.compareTo(BigDecimal.ZERO) == 1
Copy link
Collaborator

Choose a reason for hiding this comment

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

💡 I suggest using > and < operators directly improve code readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe this approach won't work in all cases when dealing with BigDecimal, because these operators internally rely on the exact scale of the BigDecimal values during comparisons. For example:

If totalAmount is BigDecimal("0.00"), it may not behave as expected when compared to BigDecimal.ZERO using > or <, as the comparison might fail due to scale differences.
Using .compareTo(BigDecimal.ZERO) is more robust because it ignores scale differences and focuses solely on the numerical value, ensuring consistent behaviour regardless of how totalAmount is constructed (e.g., 0.00 vs. 0).

Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe this approach won't work in all cases when dealing with BigDecimal, because these operators internally rely on the exact scale of the BigDecimal values during comparisons.

💡 I think this is not true, according to docs:

All comparisons are translated into calls to compareTo, which is required to return Int.

As a result, using comparison operators translates to the same call to the compareTo() function that is used currently.

You can verify that by CMD-clicking the comparison operator (>) – it will redirect to the underlying compareTo function implementation in Kotlin std lib.

I suggest using comparisons like that:

Suggested change
dataState.value.orderTotal?.compareTo(BigDecimal.ZERO) == 1
dataState.value.orderTotal!! > BigDecimal.ZERO

which compiles to:

     dataState.value.orderTotal!!.compareTo(BigDecimal.ZERO) > 0

Let me know what you think or if I'm missing something @AnirudhBhat.

💡 Another improvement would be to add a null check (throw IllegalStateException in case orderTotal) instead of allowing such illegal state in code (comparing potentially null value which will result in NPE thrown from compareTo function anyway, but throwing it earlier would make potential bug easier to debug).

@AnirudhBhat AnirudhBhat enabled auto-merge January 16, 2025 11:04
@AnirudhBhat AnirudhBhat merged commit 07de8ee into trunk Jan 16, 2025
15 checks passed
@AnirudhBhat AnirudhBhat deleted the issue/13293-remove-null-price-check branch January 16, 2025 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature: point of sale POS project type: task An internally driven task.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Woo POS][Non-Simple Products]Remove null price check for products and variations
4 participants