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] Add downloadable products filter from API and remove client side filtering #13196

Merged
merged 5 commits into from
Dec 25, 2024

Conversation

AnirudhBhat
Copy link
Contributor

@AnirudhBhat AnirudhBhat commented Dec 24, 2024

NOTE: Please review and merge this Fluxc PR before reviewing this one. Also, please update the fluxc hash in this PR before merging this PR. Thanks!

Closes: #13195

Description

This PR adds downloadable filtering for products on POS from API instead of client side filtering. The changes remain unaffected for store management.

Steps to reproduce

POS Mode

  1. Navigate to POS mode (more menu -> POS)
  2. Ensure you do not see any downloadable products
  3. Inspect network traffic from Android Studio and ensure downloadable=false is being sent in POS mode for products endpoint.

Store management mode

  1. Navigate to products tab
  2. Ensure you do see downloadable products
  3. Inspect network traffic from Android Studio and ensure there is no downloadable option is being sent in Store management mode

The tests that have been performed

Tested in both Store management and POS mode to verify downloadable filter works as expected.

Images/gif

downloadable_product.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 Dec 24, 2024
@AnirudhBhat AnirudhBhat added this to the 21.4 milestone Dec 24, 2024
@AnirudhBhat AnirudhBhat changed the base branch from trunk to issue/13189-add-tests-for-variation-data-source December 24, 2024 05:07
@AnirudhBhat AnirudhBhat requested a review from kidinov December 24, 2024 05:08
@AnirudhBhat AnirudhBhat marked this pull request as ready for review December 24, 2024 05:08
@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 24, 2024

Project dependencies changes

The following changes in project dependencies were detected (configuration vanillaReleaseRuntimeClasspath):

list
Upgraded Dependencies
org.wordpress.fluxc.plugins:woocommerce:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e, (changed from 2.101.0)
org.wordpress.fluxc:fluxc-annotations:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e, (changed from 2.101.0)
org.wordpress:fluxc:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e, (changed from 2.101.0)
tree
-+--- org.wordpress:fluxc:2.101.0
-|    +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.25 -> 2.0.21
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.21
-|    |         \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
-|    +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.3.6
-|    |    \--- androidx.annotation:annotation:1.2.0 -> 1.8.1 (*)
-|    +--- androidx.security:security-crypto:1.0.0 -> 1.1.0-alpha03
-|    |    +--- androidx.annotation:annotation:1.1.0 -> 1.8.1 (*)
-|    |    +--- com.google.crypto.tink:tink-android:1.5.0
-|    |    \--- androidx.collection:collection:1.1.0 -> 1.4.0 (*)
-|    +--- com.squareup.okhttp3:okhttp-urlconnection:4.9.0
-|    |    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.12.0 (*)
-|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10 -> 1.9.10 (*)
-|    +--- com.google.code.gson:gson:2.8.5 -> 2.10.1
-|    +--- org.apache.commons:commons-text:1.10.0 (*)
-|    +--- androidx.room:room-runtime:2.6.1 (*)
-|    +--- androidx.room:room-ktx:2.6.1
-|    |    +--- androidx.room:room-common:2.6.1 (*)
-|    |    +--- androidx.room:room-runtime:2.6.1 (*)
-|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.21 (*)
-|    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1 -> 1.8.1 (*)
-|    |    +--- androidx.room:room-common:2.6.1 (c)
-|    |    \--- androidx.room:room-runtime:2.6.1 (c)
-|    +--- com.google.dagger:dagger:2.51.1
-|    |    \--- javax.inject:javax.inject:1
-|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*)
-|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (*)
-|    +--- org.wordpress:wellsql:2.0.0
-|    |    +--- androidx.annotation:annotation:1.2.0 -> 1.8.1 (*)
-|    |    \--- org.wordpress.wellsql:wellsql-annotations:2.0.0
-|    +--- org.wordpress.fluxc:fluxc-annotations:2.101.0
-|    +--- org.greenrobot:eventbus:3.3.1 (*)
-|    +--- org.greenrobot:eventbus-java:3.3.1
-|    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.12.0 (*)
-|    +--- com.android.volley:volley:1.1.1 -> 1.2.0
-|    +--- androidx.paging:paging-runtime:2.1.2
-|    |    +--- androidx.paging:paging-common:2.1.2
-|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.8.1 (*)
-|    |    |    \--- androidx.arch.core:core-common:2.0.0 -> 2.2.0 (*)
-|    |    +--- androidx.arch.core:core-runtime:2.0.0 -> 2.2.0 (*)
-|    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.8.7 (*)
-|    |    +--- androidx.lifecycle:lifecycle-livedata:2.0.0 -> 2.8.7 (*)
-|    |    \--- androidx.recyclerview:recyclerview:1.0.0 -> 1.3.2 (*)
-|    +--- com.goterl:lazysodium-android:5.0.2
-|    +--- net.java.dev.jna:jna:5.5.0
-|    \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.25 -> 2.0.21 (*)
++--- org.wordpress:fluxc:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e
+|    +--- org.jetbrains.kotlin:kotlin-parcelize-runtime:1.9.25 -> 2.0.21
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
+|    |    \--- org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.0.21
+|    |         \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.21 (*)
+|    +--- androidx.exifinterface:exifinterface:1.0.0 -> 1.3.6
+|    |    \--- androidx.annotation:annotation:1.2.0 -> 1.8.1 (*)
+|    +--- androidx.security:security-crypto:1.0.0 -> 1.1.0-alpha03
+|    |    +--- androidx.annotation:annotation:1.1.0 -> 1.8.1 (*)
+|    |    +--- com.google.crypto.tink:tink-android:1.5.0
+|    |    \--- androidx.collection:collection:1.1.0 -> 1.4.0 (*)
+|    +--- com.squareup.okhttp3:okhttp-urlconnection:4.9.0
+|    |    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.12.0 (*)
+|    |    \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10 -> 1.9.10 (*)
+|    +--- com.google.code.gson:gson:2.8.5 -> 2.10.1
+|    +--- org.apache.commons:commons-text:1.10.0 (*)
+|    +--- androidx.room:room-runtime:2.6.1 (*)
+|    +--- androidx.room:room-ktx:2.6.1
+|    |    +--- androidx.room:room-common:2.6.1 (*)
+|    |    +--- androidx.room:room-runtime:2.6.1 (*)
+|    |    +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 -> 2.0.21 (*)
+|    |    +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1 -> 1.8.1 (*)
+|    |    +--- androidx.room:room-common:2.6.1 (c)
+|    |    \--- androidx.room:room-runtime:2.6.1 (c)
+|    +--- com.google.dagger:dagger:2.51.1
+|    |    \--- javax.inject:javax.inject:1
+|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*)
+|    +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (*)
+|    +--- org.wordpress:wellsql:2.0.0
+|    |    +--- androidx.annotation:annotation:1.2.0 -> 1.8.1 (*)
+|    |    \--- org.wordpress.wellsql:wellsql-annotations:2.0.0
+|    +--- org.wordpress.fluxc:fluxc-annotations:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e
+|    +--- org.greenrobot:eventbus:3.3.1 (*)
+|    +--- org.greenrobot:eventbus-java:3.3.1
+|    +--- com.squareup.okhttp3:okhttp:4.9.0 -> 4.12.0 (*)
+|    +--- com.android.volley:volley:1.1.1 -> 1.2.0
+|    +--- androidx.paging:paging-runtime:2.1.2
+|    |    +--- androidx.paging:paging-common:2.1.2
+|    |    |    +--- androidx.annotation:annotation:1.0.0 -> 1.8.1 (*)
+|    |    |    \--- androidx.arch.core:core-common:2.0.0 -> 2.2.0 (*)
+|    |    +--- androidx.arch.core:core-runtime:2.0.0 -> 2.2.0 (*)
+|    |    +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.8.7 (*)
+|    |    +--- androidx.lifecycle:lifecycle-livedata:2.0.0 -> 2.8.7 (*)
+|    |    \--- androidx.recyclerview:recyclerview:1.0.0 -> 1.3.2 (*)
+|    +--- com.goterl:lazysodium-android:5.0.2
+|    +--- net.java.dev.jna:jna:5.5.0
+|    \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.25 -> 2.0.21 (*)
-\--- org.wordpress.fluxc.plugins:woocommerce:2.101.0
-     +--- org.wordpress:fluxc:2.101.0 (*)
-     +--- com.google.code.gson:gson:2.8.5 -> 2.10.1
-     +--- com.google.dagger:dagger:2.51.1 (*)
-     +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*)
-     +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (*)
-     +--- androidx.room:room-runtime:2.6.1 (*)
-     +--- org.wordpress:wellsql:2.0.0 (*)
-     +--- org.wordpress.fluxc:fluxc-annotations:2.101.0
-     +--- androidx.room:room-ktx:2.6.1 (*)
-     \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.25 -> 2.0.21 (*)
+\--- org.wordpress.fluxc.plugins:woocommerce:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e
+     +--- org.wordpress:fluxc:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e (*)
+     +--- com.google.code.gson:gson:2.8.5 -> 2.10.1
+     +--- com.google.dagger:dagger:2.51.1 (*)
+     +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1 (*)
+     +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1 (*)
+     +--- androidx.room:room-runtime:2.6.1 (*)
+     +--- org.wordpress:wellsql:2.0.0 (*)
+     +--- org.wordpress.fluxc:fluxc-annotations:trunk-b329e031481c8653a57c0a41c4dedfc0ba6a510e
+     +--- androidx.room:room-ktx:2.6.1 (*)
+     \--- org.jetbrains.kotlin:kotlin-stdlib:1.9.25 -> 2.0.21 (*)

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 24, 2024

📲 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
Commitd95c4a2
Direct Downloadwoocommerce-wear-prototype-build-pr13196-d95c4a2.apk

@wpmobilebot
Copy link
Collaborator

wpmobilebot commented Dec 24, 2024

📲 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
Commitd95c4a2
Direct Downloadwoocommerce-prototype-build-pr13196-d95c4a2.apk

@codecov-commenter
Copy link

codecov-commenter commented Dec 24, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 40.59%. Comparing base (c5c1025) to head (d95c4a2).
Report is 34 commits behind head on trunk.

Additional details and impacted files
@@            Coverage Diff            @@
##              trunk   #13196   +/-   ##
=========================================
  Coverage     40.59%   40.59%           
+ Complexity     6368     6364    -4     
=========================================
  Files          1345     1345           
  Lines         77238    77238           
  Branches      10603    10601    -2     
=========================================
  Hits          31353    31353           
  Misses        43128    43128           
  Partials       2757     2757           

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

@kidinov kidinov self-assigned this Dec 24, 2024
filters = mapOf(WCProductStore.ProductFilterOption.STATUS to ProductStatus.PUBLISH.value)
filters = mapOf(
WCProductStore.ProductFilterOption.STATUS to ProductStatus.PUBLISH.value,
WCProductStore.ProductFilterOption.DOWNLOADABLE to WCProductStore.DownloadableOptions.FALSE.toString(),
Copy link
Contributor

Choose a reason for hiding this comment

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

I am thinking if DownloadableOptions actually gives us something here:

  • filter typed as <ProductFilterOption, String>
  • DownloadableOptions enum has no connections to ProductFilterOption, so it doesn't define the API anyhow

It feels like it either should be something changed in the filter type, or we rather pass false/true as strings

Wdyt?

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 see your point. My train of thought was that DownloadableOptions enforces type safety and avoids potential typos (like "flase" or "treu") in the future. Additionally, by using DownloadableOptions, developers are naturally guided toward the enum whenever changes are needed, reducing the risk of inconsistent values.

I do understand this adds a slight abstraction, but I believe the trade-off is worthwhile for the benefits of safety and maintainability. WDYT?

Copy link
Contributor

@kidinov kidinov Dec 24, 2024

Choose a reason for hiding this comment

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

@AnirudhBhat

The thing is that it doesn't enforce anything. It's the string type here. If you want actually to implement type safety, then the type should not be a string but some ProductFilterOptionFilterValue or something like that

Currently, it feels like just an enum for the sake of an enum, and there is no way anyone can figure out/find that they can/should use it as a key to the filter. So to me, it feels that it is either just a string or an actual type should be here

Wdyt?

Copy link
Contributor Author

@AnirudhBhat AnirudhBhat Dec 25, 2024

Choose a reason for hiding this comment

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

I see your point about the current implementation not fully enforcing type safety since the filter type is <ProductFilterOption, String>. You’re right that a more robust approach would involve introducing something like a ProductFilterOptionFilterValue type.

That said, even though DownloadableOptions doesn’t enforce type safety at the API level, I believe it still adds value by reducing human errors like typos ("flase" instead of "false") when setting the filter key. The enum serves as a centralised, predefined set of valid values that developers can rely on.

Additionally, the presence of DownloadableOptions makes it clear to anyone working with the code that there is a defined set of options for the DOWNLOADABLE key. I believe this will be helpful as developers will know to refer to the enum rather than hardcoding strings.

I understand the concern about discoverability. We could potentially improve this by better documenting its usage by adding a comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hey @AnirudhBhat

That said, even though DownloadableOptions doesn’t enforce type safety at the API level, I believe it still adds value by reducing human errors like typos ("flase" instead of "false") when setting the filter key. The enum serves as a centralized, predefined set of valid values that developers can rely on.

I believe others might not realize that there is an enum, especially since it's not even meant to be used as an enum but rather as a substitute for a String constant, creating more confusion.

I understand the concern about discoverability. We could potentially improve this by better documenting its usage by adding a comment.

That’s maybe another problem on its own 😀 Rather than providing the right solution, adding a comment that may become outdated or incorrect and ultimately create further issues

In any case, I think it's really a small thing, and not worth further discussion

@kidinov kidinov self-requested a review December 24, 2024 08:05
Copy link
Contributor

@kidinov kidinov left a comment

Choose a reason for hiding this comment

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

The code looks good! I left one suggestion though

What I am not sure if the API actually works. It returns me downloadable items in the response. Is this something available from a specific version of WooCore? If it's then I guess we somehow should it handle or...?

@AnirudhBhat
Copy link
Contributor Author

What I am not sure if the API actually works. It returns me downloadable items in the response. Is this something available from a specific version of WooCore?

Sorry I forgot to mention this in the PR. Yes, the changes in the API are available only from WooCommerce 9.6.0 or from the nightly build (for testing). We are thinking to add a minimum WooCommerce version as a requirement for POS users.

@kidinov kidinov self-requested a review December 24, 2024 14:08
Copy link
Contributor

@kidinov kidinov left a comment

Choose a reason for hiding this comment

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

I validated that the API works 👍

Do you think we can merge it before uping the minimum supported version? My understanding that we consider that the POS is available to the users, so we must make sure that the min version enforced before this change then, correct?

@AnirudhBhat
Copy link
Contributor Author

Do you think we can merge it before uping the minimum supported version? My understanding that we consider that the POS is available to the users, so we must make sure that the min version enforced before this change then, correct?

We’re still considering whether to make this a hard requirement or to implement checks within the app to allow users with WooCommerce versions < 9.6.0 to use POS with only simple products. Thinking more about this, I believe enforcing the check now is the better approach. This ensures compatibility and avoids potential issues, and we can always revisit and adjust this decision later if needed.

eb7d117

Base automatically changed from issue/13189-add-tests-for-variation-data-source to trunk December 25, 2024 04:55
@AnirudhBhat AnirudhBhat merged commit 0eadf66 into trunk Dec 25, 2024
15 checks passed
@AnirudhBhat AnirudhBhat deleted the issue/13195-filter-downloadable-products-api branch December 25, 2024 13:38
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] Filter for downloadable products in API
4 participants