skip to Main Content

General background of my website

The website rent rooms based on hourly rental.

I use "WooCommerce Bookings And Appointments" plugin for my website.
The plugin URL is https://www.pluginhive.com/product/woocommerce-booking-and-appointments/

The plugin support Cost Rules and I control prices for all hours.
But I can’t find solution for specific scenario.

My goal is to add rule that:

If customer choose time between 10PM to 10AM.

And the minimum order hours as bigger then 6 hours.

Then the price will be for 6 hours.

Sample room price

Booking Period set in general setting with blocks of 30 minutes.

Booking costs setting:
Minimum price for 3 hours is 300$ (we use rules for block 1 to 6).

Base cost of room: 300$ (the customer can order less then 3 hours but the price will be at least for 3 hours).

Block cost: 50$ (start from block number 7).

Scenario for example:

if customer order 4 hours from 11PM to 3AM (total blocks: 8) the price will be regular: 400$ (Base cost: 300$ + 100$ [2 blocks of 50$ each])

if customer order 5 hours from 11PM to 4AM (total blocks: 10) the price will be regular: 500$

if customer order 6 hours from 11PM to 5AM (total blocks: 12) the price will be regular: 600$

If customer order 7 hours from 11PM to 6AM (total blocks: 14) the price will be 600$ instead 700$

If customer order 8 hours from 11PM to 7AM (total blocks: 16) the price will be 600$ instead 800$

If customer order 6 hours from 9PM to 3AM (total blocks: 12) the price will be 600$

If customer order 7 hours from 9PM to 4AM (total blocks: 14) the price will be 600$ instead 700$

  • 9PM to 10PM = 100$
  • 10PM to 4AM = 600$

If customer order 8 hours from 9PM to 5AM (total blocks: 16) the price will be 600$ instead 800$

  • 9PM to 10PM = 100$
  • 10PM to 5AM = 600$ (Rule trigger because the order bigger then 6 hours)

If customer order 14 hours from 9PM to 11AM (total blocks: 28) the price will be 800$ instead 1400$

  • 9PM to 10PM = 100$
  • 10PM to 10AM = 600$ (Rule trigger because the order bigger then 6 hours)
  • 10AM to 11AM = 100$

I tried follow this post Set prices based on WooCommerce Bookings duration and make adjustments to my issue without success.

2

Answers


  1. Chosen as BEST ANSWER

    I created snippet and I don't see any change. Check this link to live preview

    <?php
    // Calculates price based on selected booking start time and minimum order hours
    add_action( 'woocommerce_before_calculate_totals', 'cwpai_booking_price_calculation', 10, 1 );
    function cwpai_booking_price_calculation( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ) {
            return;
        }
        
        foreach ( $cart->get_cart() as $cart_item ) {
            $product_id = $cart_item['product_id'];
    
            // Get start time and minimum order hours
            $start_time = strtotime($_POST['wc_bookings_field_start_date'][0] . ' ' . $_POST['wc_bookings_field_start_time'][0]);
            $minimum_hours = get_post_meta( $product_id, '_minimum_duration', true );
    
            // Check if start time and minimum order hours meet condition
            if ( date('H:i', $start_time) >= '22:00' && date('H:i', $start_time) <= '10:00' && $minimum_hours >= 6 ) {
                // Calculate maximum cost for 6 hours
                $max_cost = $cart_item['data']->get_price() * 6;
    
                // Get current cost based on duration
                $duration = WC_Bookings_Cart::calculate_booking_duration( $cart_item['booking'], true, true );
                $current_cost = $duration['cost'];
    
                // Update cost to maximum cost for 6 hours
                if ( $current_cost > $max_cost ) {
                    $cart_item['data']->set_price( $max_cost );
                }
            }
        }
    }
    
    // Update post meta when product is saved
    add_action( 'woocommerce_process_product_meta', 'cwpai_update_booking_meta' );
    function cwpai_update_booking_meta( $post_id ) {
        // Only run for bookable products
        if ( get_post_meta( $post_id, '_wc_booking_type', true ) !== 'booking' ) {
            return;
        }
        
        // Get minimum order hours
        $minimum_hours = isset( $_POST['_minimum_duration'] ) ? absint( $_POST['_minimum_duration'] ) : 0;
    
        // Update post meta with new booking cost
        if ( $minimum_hours >= 6 ) {
            $max_cost = get_post_meta( $post_id, '_price', true ) * 6;
            update_post_meta( $post_id, '_new_booking_cost', $max_cost );
        } else {
            delete_post_meta( $post_id, '_new_booking_cost' );
        }
    }
    
    // Modify product costs to new booking cost
    add_filter( 'woocommerce_product_get_price', 'cwpai_modify_product_costs', 10, 2 );
    add_filter( 'woocommerce_product_get_regular_price', 'cwpai_modify_product_costs', 10, 2 );
    function cwpai_modify_product_costs( $price, $product ) {
        $new_booking_cost = get_post_meta( $product->get_id(), '_new_booking_cost', true );
    
        if ( $new_booking_cost ) {
            $price = $new_booking_cost;
        }
    
        return $price;
    }
    

  2. I miss something 🙂 Check this link to live preview

    /**
     * Custom price calculation for WooCommerce Bookings and Appointments plugin.
     */
    
    // Hook into the 'woocommerce_before_calculate_totals' action
    add_action('woocommerce_before_calculate_totals', 'custom_booking_price_calculation', 10, 1);
    function custom_booking_price_calculation($cart) {
        if (is_admin() && !defined('DOING_AJAX'))
            return;
    
        // Get current time
        $current_time = current_time('timestamp');
    
        foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
            $product = $cart_item['data'];
    
            if ($product->is_type('booking')) {
                $booking_data = $product->get_data();
                $start_time = strtotime($booking_data['date_from']);
                $end_time = strtotime($booking_data['date_to']);
                $selected_blocks = ceil(($end_time - $start_time) / 1800); // 1800 seconds = 30 minutes
    
                // Condition #1: Start time is between 10:00 PM and 10:00 AM
                $start_hour = date('H', $start_time);
                if ($start_hour >= 22 || $start_hour <= 10) {
                    // Condition #2: Minimum order blocks greater than or equal to 12
                    if ($selected_blocks >= 12) {
                        // Condition #3: Calculate price for maximum 12 blocks based on rules
                        $base_cost = 300; // Base cost from product settings
                        $cost_per_block = 50; // Cost per block from product settings
    
                        $max_blocks = min($selected_blocks, 12);
                        $price = $base_cost + ($cost_per_block * $max_blocks);
    
                        // Set new price for the booking
                        $booking_data['cost'] = $price;
                        $booking = new WC_Booking($booking_data['booking_id']);
                        $booking->set_cost($price);
    
                        // Update booking data
                        $product->set_props($booking_data);
                        $product->save();
    
                        // Update cart item data
                        $cart_item['data'] = $product;
                        $cart->cart_contents[$cart_item_key] = $cart_item;
    
                        // Update cart totals
                        $cart->set_cart_contents_total();
                        $cart->set_cart_contents_tax();
                        $cart->set_total($cart->subtotal + $cart->tax_total, $cart->shipping_total);
                    }
                }
            }
        }
    }
    
    // Hook into the 'update_post_meta' action
    add_action('update_post_meta', 'custom_booking_price_update_post_meta', 10, 3);
    function custom_booking_price_update_post_meta($meta_id, $object_id, $meta_key) {
        if ($meta_key === '_cost') {
            $booking = new WC_Booking($object_id);
            $booking_data = $booking->get_data();
            $booking_cost = $booking_data['cost'];
    
            // Update booking cost if necessary
            if ($booking_cost) {
                update_post_meta($object_id, '_cost', $booking_cost);
            }
        }
    }
    
    // Hook into the 'new_booking_cost' filter
    add_filter('new_booking_cost', 'custom_booking_price_new_booking_cost', 10, 4);
    function custom_booking_price_new_booking_cost($cost, $resource_id, $start, $end) {
        // Check if the calculation has already been performed
        if (did_action('woocommerce_before_calculate_totals') >= 2) {
            return $cost;
        }
    
        // Calculate the number of blocks
        $selected_blocks = ceil(($end - $start) / 1800);
    
        // Condition #1: Start time is between 10:00 PM and 10:00 AM
        $start_hour = date('H', $start);
        $start_minute = date('i', $start);
        if (($start_hour == 22 && $start_minute >= 0) || ($start_hour >= 23 || $start_hour <= 9)) {
            // Condition #2: Minimum order blocks greater than or equal to 12
            if ($selected_blocks >= 12) {
                // Condition #3: Calculate price for maximum 12 blocks based on rules
                $base_cost = 300; // Base cost from product settings
                $cost_per_block = 50; // Cost per block from product settings
    
                $max_blocks = min($selected_blocks, 12);
                $price = $base_cost + ($cost_per_block * $max_blocks);
    
                return $price;
            }
        }
    
        return $cost;
    }
    
    
    
    
    // Function to modify the base cost of a bookable product
    function modify_baseprice($base_cost, $product_id, $booking_id) {
        $product = wc_get_product($product_id);
    
        if ($product->is_type('booking')) {
            $booking_base_cost = $product->get_meta('_cost');
    
            if ($booking_base_cost) {
                $booking_base_cost = max(0, (float)$booking_base_cost);
                $product->set_base_cost($booking_base_cost);
                $product->save();
                return $booking_base_cost;
            }
        }
    
        return $base_cost;
    }
    
    
    // Hook into the 'woocommerce_bookings_after_booking_base_cost' action
    add_action('woocommerce_bookings_after_booking_base_cost', 'modify_baseprice', 10, 3);
    
    
    
    
    // Hook into the 'woocommerce_process_product_meta_booking' action
    add_action('woocommerce_process_product_meta_booking', 'modify_bookable_product_base_cost', 100, 1);
    function modify_bookable_product_base_cost($product_id) {
        if (isset($_POST['_cost'])) {
            $booking_base_cost = max(0, (float)$_POST['_cost']);
            update_post_meta($product_id, '_base_cost', $booking_base_cost);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search