woocommerce / woocommerce-accommodation-bookings

An accommodations add-on for the WooCommerce Bookings extension.
86 stars 31 forks source link

Price for sorting is incorrect #434

Open axi opened 1 month ago

axi commented 1 month ago

What I expected

I expect the orderby=price-asc order by to be working correctly

What happened instead

Values saved in lookup_table are wrong, resulting order is wrong

Steps to reproduce the issue

Note: It looks like this happen only after an "update", not on creation.

Create an accommodation product with the following:

Create another accommodation product with the following:

When using sorting by price asc, we want the cheapest first (Product1) but we have Product2 first. This is because lookup_table gets a calculated value that take the min number of nights into account...

Check the following query

SELECT
    pm.post_id,
    pml.min_price,
    pm2.meta_value as '_price',
    pm3.meta_value as '_wc_booking_min_duration'
FROM wp_postmeta pm
    LEFT JOIN wp_wc_product_meta_lookup pml ON pml.product_id = pm.post_id
    LEFT JOIN wp_postmeta pm2 ON pm.post_id = pm2.post_id AND pm2.meta_key = '_price'
    LEFT JOIN wp_postmeta pm3 ON pm.post_id = pm3.post_id AND pm3.meta_key = '_wc_booking_min_duration'
WHERE pm.post_id IN (MY_CREATED_PRODUCT_IDS)
GROUP BY pm.post_id
ORDER BY pm.post_id

WC_Accommodation_Booking_Admin_Panels::save_product_data() tries to solve that l424:

public function save_product_data( $post_id ) {
    ....
    // Set price so filters work - using get_base_cost()
    $product = wc_get_product( $post_id );
    update_post_meta( $post_id, '_price', $product->get_base_cost() );
}

but at that time, price is already set in lookup table.


axi commented 1 month ago

My quickfix right before the closing of the WC_Accommodation_Booking_Admin_Panels::save_product_data() method

        // Quick Fix
        $wpdb->update(
            $wpdb->prefix . 'wc_product_meta_lookup',
            [
                'min_price' => $product->get_base_cost(),
                'max_price' => $product->get_base_cost(),
            ],
            [
                'product_id' => $post_id,
            ],
            '%d'
        );