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

Fix for product meta lookup table incorrectly marking a product as onsale Closes #43008 #43011

Merged
merged 6 commits into from Mar 1, 2024

Conversation

pintend
Copy link
Contributor

@pintend pintend commented Dec 20, 2023

Determine if a product is on sale based on regular price, which is how its done in the WC_Product class

if ( '' !== (string) $this->get_sale_price( $context ) && $this->get_regular_price( $context ) > $this->get_sale_price( $context ) ) {

Currently $product->is_on_sale() == false when _regular_price and _sale_price are the same, but the product lookup table ignores the _regular_price and only checks that _price and _sale_price are the same.

Submission Review Guidelines:

Changes proposed in this Pull Request:

Closes #43008 .

How to test the changes in this Pull Request:

  1. Create a simple test product in WC > Products. Make sure it's not "on sale" and take note of its ID.
  2. Force an update of the meta lookup table by running wp eval "wc_update_product_lookup_tables_column( 'onsale' );".
  3. Confirm the product is not on sale in the lookup table:
    > wp db query "SELECT onsale FROM $(wp db prefix)wc_product_meta_lookup WHERE product_id = <product_id>;"
    +--------+
    | onsale |
    +--------+
    |      0 |
    +--------+
    
  4. Now go back and edit the product and set a sale price.
  5. Confirm that the product appears on sale in the lookup table:
    > wp db query "SELECT onsale FROM $(wp db prefix)wc_product_meta_lookup WHERE product_id = <product_id>;"
    +--------+
    | onsale |
    +--------+
    |      1 |
    +--------+
    
  6. To simulate the product having regular_price, sale_price and price all set to the same value run the following command:
    wp post meta update <product_id> _sale_price `wp post meta get <product_id> _regular_price`
    wp post meta update <product_id> _price `wp post meta get <product_id> _regular_price`
    Not that this is only to expedite testing, but this is in fact possible via the admin UI if one disables frontend validation (for example, by disabling JS).
  7. Force (again) an update of the meta lookup table by running wp eval "wc_update_product_lookup_tables_column( 'onsale' );".
  8. Confirm that the product is not marked as being on sale in the lookup tables:
    > wp db query "SELECT onsale FROM $(wp db prefix)wc_product_meta_lookup WHERE product_id = <product_id>;"
    +--------+
    | onsale |
    +--------+
    |      0 |
    +--------+
    

Changelog entry

  • Automatically create a changelog entry from the details below.

Significance

  • Patch
  • Minor
  • Major

Type

  • Fix - Fixes an existing bug
  • Add - Adds functionality
  • Update - Update existing functionality
  • Dev - Development related task
  • Tweak - A minor adjustment to the codebase
  • Performance - Address performance issues
  • Enhancement - Improvement to existing functionality

Message

Use regular_price to determine if product is not sale and don't rely only on price for product_meta_lookup

Comment

@github-actions github-actions bot added plugin: woocommerce Issues related to the WooCommerce Core plugin. type: community contribution labels Dec 20, 2023
@woocommercebot woocommercebot requested review from a team and jorgeatorres and removed request for a team December 20, 2023 19:21
Copy link
Contributor

Hi ,

Apart from reviewing the code changes, please make sure to review the testing instructions as well.

You can follow this guide to find out what good testing instructions should look like:
https://github.com/woocommerce/woocommerce/wiki/Writing-high-quality-testing-instructions

@jorgeatorres jorgeatorres reopened this Jan 8, 2024
Copy link
Member

@jorgeatorres jorgeatorres left a comment

Choose a reason for hiding this comment

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

Hi @pintend!

Thanks for your contribution 💯. I left some feedback regarding a tiny change that we would need to make in order for this to work as intended.

Let me know what you think!

Copy link
Contributor Author

@pintend pintend left a comment

Choose a reason for hiding this comment

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

did i miss that in the commit? i had it in my test query AND CAST(meta3.meta_value AS DECIMAL(10, 2)) > CAST(meta2.meta_value AS DECIMAL(10, 2))

@jorgeatorres
Copy link
Member

jorgeatorres commented Jan 9, 2024

@pintend: You did use DECIMAL(10, 2) in the testing instructions, but the code itself uses a placeholder for the decimal places (%d) which is correct, but then you need to provide the actual value.

CAST( meta1.meta_value AS DECIMAL ) >= 0
AND CAST( meta2.meta_value AS CHAR ) != ''
AND CAST( meta1.meta_value AS DECIMAL( 10, %d ) ) = CAST( meta2.meta_value AS DECIMAL( 10, %d ) )
AND CAST( meta3.meta_value AS DECIMAL( 10, %d ) ) > CAST( meta2.meta_value AS DECIMAL( 10, %d ) )
, 1, 0 )
",
$decimals,
$decimals

@jorgeatorres jorgeatorres added the needs: author feedback The issue/PR needs a response from any of the parties involved in the issue. label Jan 9, 2024
@jorgeatorres
Copy link
Member

Hey @pintend,

Thanks for making the changes. I was testing this again and now I'm wondering where the original bug came from. Using the set_price(), set_regular_price() and set_sale_price() functions I can't set a sale price that is equal to the price/regular price. In all cases, the price property updates to the proper amount, which is what the lookup table uses (as you mentioned).

We recently merged fixes related to product sales, so something might've changed.

Is there a way to reproduce this that doesn't involve changing the metadata directly in the database? This is not necessarily supported. Hardening the lookup update might still make sense, but I'd like to understand if there's something else we're missing.

@pintend
Copy link
Contributor Author

pintend commented Feb 21, 2024

@jorgeatorres: The issue started when a 3rd party plugin created and updated product records directly in the db, although the issue should really be fixed in that plugin (which I don't have control over) I don't see the harm "fixing" it here as well, especially when in the application this is the method it uses to determine if its on sale... might as well keep the logic consistent.

Although the functions dont allow a developer to create this issue, some developers might and do go around those helper functions. adding this extra check should be a safe change that protects from that even if its "useless" for most cases

if the sale_price is not blank and regular_price is more than the sale_price

if ( '' !== (string) $this->get_sale_price( $context ) && $this->get_regular_price( $context ) > $this->get_sale_price( $context ) ) {

if the sale_price is not blank and the price and sale_price are equal

AND CAST( meta1.meta_value AS DECIMAL( 10, %d ) ) = CAST( meta2.meta_value AS DECIMAL( 10, %d ) )

my change:

if the sale_price is not blank and regular_price is more than the sale_price and the price and sale_price are equal

AND CAST( meta3.meta_value AS DECIMAL( 10, %d ) ) > CAST( meta2.meta_value AS DECIMAL( 10, %d ) )

it make it more consistent and prevents the issue from other plugins

Copy link
Member

@jorgeatorres jorgeatorres left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for your patience here @pintend and for this fix. It works great.

FYI I edited the first comment by adding some testing instructions to make it easier for our team to confirm this is working correctly.

@jorgeatorres jorgeatorres merged commit bf84ed5 into woocommerce:trunk Mar 1, 2024
32 of 33 checks passed
@github-actions github-actions bot added this to the 8.8.0 milestone Mar 1, 2024
@github-actions github-actions bot added the needs: analysis Indicates if the PR requires a PR testing scrub session. label Mar 1, 2024
@alopezari alopezari added needs: internal testing Indicates if the PR requires further testing conducted by Solaris status: analysis complete Indicates if a PR has been analysed by Solaris and removed needs: analysis Indicates if the PR requires a PR testing scrub session. labels Mar 4, 2024
thealexandrelara pushed a commit that referenced this pull request Mar 4, 2024
…sale Closes #43008 (#43011)

* Update wc-product-functions.php

Determine if a product is on sale based on regular price, which is how its done in the WC_Product class https://github.com/woocommerce/woocommerce/blob/7122669d448acb90d0f8a7177b76baaccec2e76b/plugins/woocommerce/includes/abstracts/abstract-wc-product.php#L1633

* Add changefile(s) from automation for the following project(s): woocommerce

* added missing placeholders

* Update 43011-patch-1

* Add changefile(s) from automation for the following project(s): woocommerce

* Re-trigger CI

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Jorge A. Torres <jorge.torres@automattic.com>
Konamiman pushed a commit that referenced this pull request Mar 13, 2024
…sale Closes #43008 (#43011)

* Update wc-product-functions.php

Determine if a product is on sale based on regular price, which is how its done in the WC_Product class https://github.com/woocommerce/woocommerce/blob/7122669d448acb90d0f8a7177b76baaccec2e76b/plugins/woocommerce/includes/abstracts/abstract-wc-product.php#L1633

* Add changefile(s) from automation for the following project(s): woocommerce

* added missing placeholders

* Update 43011-patch-1

* Add changefile(s) from automation for the following project(s): woocommerce

* Re-trigger CI

---------

Co-authored-by: github-actions <github-actions@github.com>
Co-authored-by: Jorge A. Torres <jorge.torres@automattic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs: author feedback The issue/PR needs a response from any of the parties involved in the issue. needs: internal testing Indicates if the PR requires further testing conducted by Solaris plugin: woocommerce Issues related to the WooCommerce Core plugin. status: analysis complete Indicates if a PR has been analysed by Solaris type: community contribution
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Product meta lookup table incorrectly shows product on sale
3 participants