woocommerce / woocommerce-android

WooCommerce Android app
https://www.woocommerce.com/mobile
GNU General Public License v2.0
277 stars 135 forks source link

Unable to set 0 price for products #3496

Closed reginabally closed 2 years ago

reginabally commented 3 years ago

Describe the bug

It was reported in 3689003-zen that if a product was created or edited on the WCAndroid app and set the price to 0, the product shows the "Read More" button on the Shop page instead of "Add to Cart".

I was able to reproduce this on WCAndroid but not on WCiOS.

To Reproduce Steps to reproduce the behavior:

  1. Go to Products
  2. Create a new product or edit an existing product
  3. Enter 0.00 as the price
  4. Publish/save the product
  5. Visit the Shop page and see that the product has a "Read More" button instead of "Add to Cart"
  6. Visiting the product page will not see an option to add the product to the cart as well.

Sample Shop page: https://woo20200908.mystagingwebsite.com/product-category/uncategorized/

Sample product page: https://woo20200908.mystagingwebsite.com/product/free-product/

Expected behavior

I would expect the app to allow me to set the product price to 0 so it can be added to the cart as a free product.

Sample product page with $0 price that can be added to the cart: https://woo20200908.mystagingwebsite.com/product/test-free-product/

Isolating the problem (mark completed items with an [x]):

Mobile Environment Please include:

WordPress Environment

``` ` ### WordPress Environment ### WordPress address (URL): https://woo20200908.mystagingwebsite.com Site address (URL): https://woo20200908.mystagingwebsite.com WC Version: 4.9.2 REST API Version: ✔ 4.9.2 WC Blocks Version: ✔ 4.0.0 Action Scheduler Version: ✔ 3.1.6 WC Admin Version: ✔ 1.8.3 Log Directory Writable: ✔ WP Version: 5.6 WP Multisite: – WP Memory Limit: 256 MB WP Debug Mode: ✔ WP Cron: ✔ Language: en_US External object cache: ✔ ### Server Environment ### Server Info: nginx PHP Version: 7.3.26 PHP Post Max Size: 2 GB PHP Time Limit: 1200 PHP Max Input Vars: 6144 cURL Version: 7.74.0 OpenSSL/1.1.1d SUHOSIN Installed: – MySQL Version: 5.5.5-10.3.24-MariaDB-log Max Upload Size: 2 GB Default Timezone is UTC: ✔ fsockopen/cURL: ✔ SoapClient: ✔ DOMDocument: ✔ GZip: ✔ Multibyte String: ✔ Remote Post: ✔ Remote Get: ✔ ### Database ### WC Database Version: 4.9.2 WC Database Prefix: wp_ Total Database Size: 6.70MB Database Data Size: 4.72MB Database Index Size: 1.98MB wp_woocommerce_sessions: Data: 0.05MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_api_keys: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_attribute_taxonomies: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_downloadable_product_permissions: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_woocommerce_order_items: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_order_itemmeta: Data: 0.06MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_tax_rates: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_woocommerce_tax_rate_locations: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_shipping_zones: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_woocommerce_shipping_zone_locations: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_shipping_zone_methods: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_woocommerce_payment_tokens: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_woocommerce_payment_tokenmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_woocommerce_log: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_actions: Data: 0.02MB + Index: 0.11MB + Engine InnoDB wp_actionscheduler_claims: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_groups: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_actionscheduler_logs: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_commentmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_comments: Data: 0.02MB + Index: 0.09MB + Engine InnoDB wp_links: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_mo2f_network_blocked_ips: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_mo2f_network_email_sent_audit: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_mo2f_network_transactions: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_mo2f_network_whitelisted_ips: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_mo2f_user_details: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_mo2f_user_login_info: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_options: Data: 0.30MB + Index: 0.06MB + Engine InnoDB wp_postmeta: Data: 0.22MB + Index: 0.14MB + Engine InnoDB wp_posts: Data: 0.14MB + Index: 0.06MB + Engine InnoDB wp_termmeta: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_terms: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_term_relationships: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_term_taxonomy: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_usermeta: Data: 0.05MB + Index: 0.03MB + Engine InnoDB wp_users: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wc_admin_notes: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_admin_note_actions: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wc_category_lookup: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_customer_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_download_log: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_order_coupon_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_order_product_lookup: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_wc_order_stats: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wc_order_tax_lookup: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wc_product_meta_lookup: Data: 0.02MB + Index: 0.09MB + Engine InnoDB wp_wc_reserved_stock: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wc_tax_rate_classes: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wc_webhooks: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wfblockediplog: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wfblocks7: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wfconfig: Data: 0.47MB + Index: 0.00MB + Engine InnoDB wp_wfcrawlers: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wffilechanges: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wffilemods: Data: 0.42MB + Index: 0.00MB + Engine InnoDB wp_wfhits: Data: 0.06MB + Index: 0.05MB + Engine InnoDB wp_wfhoover: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wfissues: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_wfknownfilelist: Data: 1.52MB + Index: 0.00MB + Engine InnoDB wp_wflivetraffichuman: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wflocs: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wflogins: Data: 0.02MB + Index: 0.03MB + Engine InnoDB wp_wfls_2fa_secrets: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wfls_settings: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wfnotifications: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wfpendingissues: Data: 0.02MB + Index: 0.06MB + Engine InnoDB wp_wfreversecache: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wfsnipcache: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wfstatus: Data: 0.09MB + Index: 0.03MB + Engine InnoDB wp_wftrafficrates: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_attack_logs: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_backup_report: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_files_scan: Data: 0.02MB + Index: 0.02MB + Engine InnoDB wp_wpns_ip_rate_details: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_malware_hash_file: Data: 0.02MB + Index: 0.05MB + Engine InnoDB wp_wpns_malware_scan_report: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_malware_scan_report_details: Data: 0.02MB + Index: 0.00MB + Engine InnoDB wp_wpns_malware_skip_files: Data: 0.02MB + Index: 0.00MB + Engine InnoDB ### Post Type Counts ### attachment: 56 page: 9 post: 3 product: 32 product_variation: 20 revision: 9 seedprod: 1 shop_coupon: 1 shop_order: 22 shop_order_refund: 2 wc_order_status: 7 ### Security ### Secure connection (HTTPS): ✔ Hide errors from visitors: ✔ ### Active Plugins (2) ### Jetpack by WordPress.com: by Automattic – 9.3.2 WooCommerce: by Automattic – 4.9.2 ### Inactive Plugins (13) ### Akismet Anti-Spam: by Automattic – 4.1.8 All in One Product Quantity for WooCommerce: by WPWhale – 3.6 Coming Soon Page, Maintenance Mode & Landing Pages by SeedProd: by SeedProd – 6.0.10.1 Custom Order Status for WooCommerce: by Tyche Softwares – 2.0.1 Enable jQuery Migrate Helper: by The WordPress Team – 1.3.0 Extra Product Options (Product Addons) for WooCommerce: by ThemeHigh – 3.0.1 miniOrange 2 Factor Authentication: by miniOrange – 5.4.30 Under Construction: by WebFactory Ltd – 3.86 WooCommerce Order Status Manager: by SkyVerge – 1.13.0 WooCommerce Shipment Tracking: by WooCommerce – 1.6.26 WooCommerce Stripe Gateway: by WooCommerce – 4.7.0 Wordfence Security: by Wordfence – 7.4.14 XML-RPC Validator: by Danilo E – 0.1 ### Dropin Plugins (2) ### advanced-cache.php: advanced-cache.php object-cache.php: Memcached ### Settings ### API Enabled: – Force SSL: – Currency: USD ($) Currency Position: left Thousand Separator: , Decimal Separator: . Number of Decimals: 2 Taxonomies: Product Types: external (external) grouped (grouped) simple (simple) variable (variable) Taxonomies: Product Visibility: exclude-from-catalog (exclude-from-catalog) exclude-from-search (exclude-from-search) featured (featured) outofstock (outofstock) rated-1 (rated-1) rated-2 (rated-2) rated-3 (rated-3) rated-4 (rated-4) rated-5 (rated-5) Connected to WooCommerce.com: – ### WC Pages ### Shop base: #104 - /shop/ Cart: #105 - /cart/ Checkout: #106 - /checkout/ My account: #107 - /my-account/ Terms and conditions: ❌ Page not set ### Theme ### Name: Storefront Version: 3.4.0 Author URL: https://woocommerce.com/ Child Theme: ❌ – If you are modifying WooCommerce on a parent theme that you did not build personally we recommend using a child theme. See: How to create a child theme WooCommerce Support: ✔ ### Templates ### Overrides: – ### Action Scheduler ### Complete: 23 Oldest: 2020-12-28 09:17:34 +0000 Newest: 2021-01-28 05:37:25 +0000 ` ```
hafizrahman commented 3 years ago

Looked into this and it looks like the behavior is like this in core:

  1. By default when creating a product, the regular price field is empty. If a product is saved in this state, it turns into a Product with "Read more" button/a null-price Product.
  2. When such product is edited, the regular price field is empty.
  3. If the regular price field is set as 0, then the product is saved, it turns into a Product with 0 price that can be added to cart.

For comparison, in app:

  1. By default when creating a product, the regular price field is shown as 0. If a product is saved in this state, it turns into a Product with "Read more" button/a null-price Product.
  2. When such product is edited, the regular price field is then empty.
  3. If the regular price field is intentionally filled with 0, then user presses back from the Price screen, the 0 value is not retained and the "Add Price" panel remains empty. If the user taps "Add Price" again, the field stays empty instead of having the 0 value.

So in other words it seems like:

  1. There's no way to set a price to 0 in the app because something will change it to empty during transition from Price editing screen to Product detail screen.
  2. By default during product creation, the app should show empty regular price field to match core behavior.
  3. The app should treat empty and 0 value differently and allow 0 price value to be saved.
hafizrahman commented 3 years ago

something will change it to empty during transition from Price editing screen to Product detail screen.

Traced down this behavior to this line in PriceUtils:

https://github.com/woocommerce/woocommerce-android/blob/a3a272a5ba26cde5c13fae6c6c2aaea9ad0b017b/WooCommerce/src/main/kotlin/com/woocommerce/android/util/PriceUtils.kt#L27

Where a zero value is equal to isNotSet:

https://github.com/woocommerce/woocommerce-android/blob/a3a272a5ba26cde5c13fae6c6c2aaea9ad0b017b/WooCommerce/src/main/kotlin/com/woocommerce/android/extensions/BigDecimalExt.kt#L18

reginabally commented 2 years ago

This was mentioned in an app review:

An urgent request: accept 0 as price entry. If I manage a product via the app that should be free, I enter 0 or 0.00 and it is NOT considered as entering a number (0€) but as NO ENTRY (no price defined). This removes the option to put the product in the shopping cart on the shop page!

Date of review: Feb 21, 2022 Device: Samsung Galaxy A12 App version name: 8.4.1 Android version: Android 11 (SDK 30)

anitaa1990 commented 2 years ago

I tested again using the latest android and iOS apps and this is still happening only in Android. I seem to remember a similar issue happening when Products was first released so I searched and found this issue. I'll work on this one tomorrow and open a PR, hopefully before this sprint ends 😅

hichamboushaba commented 2 years ago

Thanks for working on this @anitaa1990, I was planning on working on it later since this PR is merged, but you beat me to it 🙏 💯.

I'll prepare an additional small PR next week to migrate back to WCMaterialOutlinedCurrencyEditTextView as it handles the currency prefix/suffix correctly now by itself, and this would allow removing this logic from the ViewModel/Fragment.