Skip to content

Commit

Permalink
Update currency conversion method for booking products
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelzaleski committed Dec 23, 2024
1 parent 952e431 commit 5f0683c
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 19 deletions.
62 changes: 43 additions & 19 deletions includes/multi-currency/Compatibility/WooCommerceBookings.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use WCPay\MultiCurrency\FrontendCurrencies;
use WCPay\MultiCurrency\MultiCurrency;
use WCPay\MultiCurrency\Utils;
use WC_Product;

/**
* Class that controls Multi Currency Compatibility with WooCommerce Bookings Plugin.
Expand Down Expand Up @@ -43,22 +44,44 @@ public function init() {
// Add needed actions and filters if Bookings is active.
if ( class_exists( 'WC_Bookings' ) ) {
if ( ! is_admin() || wp_doing_ajax() ) {
add_filter( 'woocommerce_bookings_calculated_booking_cost', [ $this, 'adjust_amount_for_calculated_booking_cost' ], 50, 1 );
add_filter( 'woocommerce_product_get_block_cost', [ $this, 'get_price' ], 50, 1 );
add_filter( 'woocommerce_product_get_cost', [ $this, 'get_price' ], 50, 1 );
add_filter( 'woocommerce_product_get_display_cost', [ $this, 'get_price' ], 50, 1 );
add_filter( 'woocommerce_product_booking_person_type_get_block_cost', [ $this, 'get_price' ], 50, 1 );
add_filter( 'woocommerce_product_booking_person_type_get_cost', [ $this, 'get_price' ], 50, 1 );
add_filter( 'woocommerce_product_get_resource_base_costs', [ $this, 'get_resource_prices' ], 50, 1 );
add_filter( 'woocommerce_product_get_resource_block_costs', [ $this, 'get_resource_prices' ], 50, 1 );
add_filter( MultiCurrency::FILTER_PREFIX . 'should_convert_product_price', [ $this, 'should_convert_product_price' ] );
add_filter( MultiCurrency::FILTER_PREFIX . 'should_convert_product_price', [ $this, 'should_convert_product_price' ], 50, 2 );
add_action( 'wp_ajax_wc_bookings_calculate_costs', [ $this, 'add_wc_price_args_filter_for_ajax' ], 9 );
add_action( 'wp_ajax_nopriv_wc_bookings_calculate_costs', [ $this, 'add_wc_price_args_filter_for_ajax' ], 9 );
}
}
}

/**
* Returns the price for an item.
* Adjusts the calculated booking cost for the selected currency, applying rounding and charm pricing as necessary.
*
* @param mixed $costs The original calculated booking costs.
* @return mixed The booking cost adjusted for the selected currency.
*/
public function adjust_amount_for_calculated_booking_cost( $costs ) {
/**
* Prevents adjustment of the calculated booking cost during cart addition.
*
* When a booking is added to the cart, the Booking plugin calculates the booking cost and
* overrides the cart item price with this calculated amount. To avoid interfering with this process,
* this function skips any additional adjustments at this stage.
*/
if ( $this->utils->is_call_in_backtrace( [ 'WC_Cart->add_to_cart' ] ) ) {
return $costs;
}

return $this->multi_currency->adjust_amount_for_selected_currency( $costs );
}

/**
* Retrieves the price for an item, converting it based on the selected currency and context.
*
* @param mixed $price The item's price.
*
Expand All @@ -68,7 +91,19 @@ public function get_price( $price ) {
if ( ! $price ) {
return $price;
}
return $this->multi_currency->get_price( $price, 'product' );

// Skip conversion during specific booking cost calculations to avoid double conversion.
if ( $this->utils->is_call_in_backtrace( [ 'WC_Cart->add_to_cart' ] ) && $this->utils->is_call_in_backtrace( [ 'WC_Bookings_Cost_Calculation::calculate_booking_cost' ] ) ) {
return $price;
}

/**
* When showing the price in HTML, the function applies currency conversion, charm pricing,
* and rounding. For internal calculations, it uses the raw exchange rate, with charm pricing
* and rounding adjustments applied only to the final calculated amount (handled in
* adjust_amount_for_calculated_booking_cost).
*/
return $this->multi_currency->get_price( $price, $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price_html' ] ) ? 'product' : 'exchange_rate' );
}

/**
Expand All @@ -90,28 +125,17 @@ public function get_resource_prices( $prices ) {
/**
* Checks to see if the product's price should be converted.
*
* @param bool $return Whether to convert the product's price or not. Default is true.
* @param bool $return Whether to convert the product's price or not. Default is true.
* @param WC_Product $product The product instance being checked.
*
* @return bool True if it should be converted.
*/
public function should_convert_product_price( bool $return ): bool {
// If it's already false, return it.
if ( ! $return ) {
public function should_convert_product_price( bool $return, WC_Product $product ): bool {
// If it's already false, or the product is not a booking, ignore it.
if ( ! $return || $product->get_type() !== 'booking' ) {
return $return;
}

// This prevents a double conversion of the price in the cart.
if ( $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price' ] ) ) {
$calls = [
'WC_Cart_Totals->calculate_item_totals',
'WC_Cart->get_product_price',
'WC_Cart->get_product_subtotal',
];
if ( $this->utils->is_call_in_backtrace( $calls ) ) {
return false;
}
}

// Fixes price display on product page and in shop.
if ( $this->utils->is_call_in_backtrace( [ 'WC_Product_Booking->get_price_html' ] ) ) {
return false;
Expand Down
14 changes: 14 additions & 0 deletions includes/multi-currency/MultiCurrency.php
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,20 @@ public function is_initialized(): bool {
return static::$is_initialized;
}

/**
* Adjusts the given amount for the currently selected currency.
*
* Applies charm pricing if specified, and adjusts the amount according to
* the selected currency's conversion rate.
*
* @param float $amount The original amount to adjust.
* @param bool $apply_charm_pricing Optional. Whether to apply charm pricing to the adjusted amount. Default true.
* @return float The amount adjusted for the selected currency.
*/
public function adjust_amount_for_selected_currency( $amount, $apply_charm_pricing = true ) {
return $this->get_adjusted_price( $amount, $apply_charm_pricing, $this->get_selected_currency() );
}

/**
* Gets the price after adjusting it with the rounding and charm settings.
*
Expand Down

0 comments on commit 5f0683c

Please sign in to comment.