1

Looking for some help, The aim is to capture several bits of data when a customer checks-out and for these to be stored as custom order item meta data.

Im looking to capture

  • Start-date
  • Start time
  • End date
  • End time

For each order, currently using WooCommerce booking and this data goes straight to the reservation area and doesn't appear as custom order item meta data.

Ive found a list of the hooks and filters whilst trying to create code myself, however I think im missing some bits along the way:

Ive tried to create this code to add these items to the custom order item meta data but without much success.

function my_custom_checkout_field_update_order_meta( $order_id ) {
    if ( ! empty( $fields['woocommerce_bookings_after_booking_base_cost'] ) ) {
        update_post_meta( $order_id, 'woocommerce_bookings_after_booking_base_cost', sanitize_text_field( $_POST['woocommerce_bookings_after_booking_base_cost'] ) );
    }
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
    echo '<p><strong>'.__('woocommerce_bookings_after_booking_base_cost').':</strong> <br/>' . get_post_meta( $order->get_id(), 'woocommerce_bookings_after_booking_base_cost', true ) . '</p>';
}

Im hoping someone has had this issue before and can share their knowledge or someone could point me in the right direction or help me with the coding, happy to admit I'm not the very best at coding but if someone could help break it down to me a little of where and what Im doing wrong, maybe what I'm doing correct as well, so I can understand how to improve.

Any help?

I also found this code, but it doesn't set the custom order meta data,

WOE_Bookings{
    function __construct() {
        add_filter('woe_get_order_product_fields',array($this,'add_product_fields') );
        add_filter('woe_get_order_product_item',array($this,'fetch_booking') );
        
        //set global filters
        add_filter('woe_get_order_product_value_booking_status', array($this,'get_booking_field_status'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_start_date', array($this,'get_booking_field_start_date'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_start_time', array($this,'get_booking_field_start_time'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_end_date', array($this,'get_booking_field_end_date'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_end_time', array($this,'get_booking_field_end_time'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_resource', array($this,'get_booking_field_resource'), 10, 5 );
        add_filter('woe_get_order_product_value_booking_persons_total', array($this,'get_booking_field_persons_total'), 10, 5 );
        
        // add function for person types 
        if( class_exists("WC_Product_Booking_Data_Store_CPT") AND method_exists("WC_Product_Booking_Data_Store_CPT", "get_person_types_ids") ) {
            $person_types_ids = WC_Product_Booking_Data_Store_CPT::get_person_types_ids();
            foreach($person_types_ids as $type_id) {
                add_filter('woe_get_order_product_value_booking_person_type_'.$type_id, function($value,$order, $item, $product, $item_meta) use ($type_id){
                    if (!$this->booking) 
                        return $value;
                    $counters = $this->booking->get_person_counts();
                    return isset($counters[$type_id]) ? $counters[$type_id] : 0;
                }, 10, 5 );
            }   
        }
    }   
    
    function add_product_fields($fields) {
        $fields['booking_status'] = array('label'=>'Booking Status','colname'=>'Booking Status','checked'=>1);
        $fields['booking_start_date'] = array('label'=>'Booking Start Date','colname'=>'Booking Start Date','checked'=>1);
        $fields['booking_start_time'] = array('label'=>'Booking Start Time','colname'=>'Booking Start Time','checked'=>1);
        $fields['booking_end_date'] = array('label'=>'Booking End Date','colname'=>'Booking End Date','checked'=>1);
        $fields['booking_end_time'] = array('label'=>'Booking End Time','colname'=>'Booking End Time','checked'=>1);
        $fields['booking_resource'] = array('label'=>'Booking Resource','colname'=>'Booking Resource','checked'=>1);
        $fields['booking_persons_total'] = array('label'=>'Booking # of Persons','colname'=>'Booking Persons Total','checked'=>1,'segment'=>'cart');
        
        // add person types as columns 
        if( class_exists("WC_Product_Booking_Data_Store_CPT") AND method_exists("WC_Product_Booking_Data_Store_CPT", "get_person_types_ids") ) {
            $person_types_ids = WC_Product_Booking_Data_Store_CPT::get_person_types_ids();
            foreach($person_types_ids as $type_id) {
                $post = get_post($type_id);
                if( $post  )
                    $fields['booking_person_type_'.$type_id] = array('label'=>'Booking Persons - ' .$post->post_title,'colname'=>'Booking Persons - ' .$post->post_title,'checked'=>1);
            }   
        }
        return $fields;
    }
    
    // booking for item 
    function fetch_booking($item) {
        global $wpdb;
        $this->booking = false;
        $booking_id = $wpdb->get_var( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key= '_booking_order_item_id' AND meta_value=" . intval( $item->get_id() ) );
        if( $booking_id ) {
            $this->booking =  new WC_Booking($booking_id);
        }
        return $item;
    }
    
    function get_booking_field_status($value,$order, $item, $product, $item_meta) {
        return $this->booking ? $this->booking->get_status() : $value;
    }       
    function get_booking_field_start_date($value,$order, $item, $product, $item_meta) {
        return $this->booking ? date_i18n( wc_date_format(), $this->booking->start) : $value;
    }       
    function get_booking_field_start_time($value,$order, $item, $product, $item_meta) {
        return $this->booking ? date_i18n( wc_time_format(), $this->booking->start) : $value;
    }       
    function get_booking_field_end_date($value,$order, $item, $product, $item_meta) {
        return $this->booking ? date_i18n( wc_date_format(), $this->booking->end) : $value;
    }       
    function get_booking_field_end_time($value,$order, $item, $product, $item_meta) {
        return $this->booking ? date_i18n( wc_time_format(), $this->booking->end) : $value;
    }       
    function get_booking_field_resource($value,$order, $item, $product, $item_meta) {
        if (!$this->booking) 
            return $value;
        $resource = $this->booking->get_resource();
        return $resource ? $resource->get_name() : $value;
    }       
    function get_booking_field_persons_total($value,$order, $item, $product,$item_meta) {
        return $this->booking ? $this->booking->get_persons_total() : $value;
    }       
}   
new WOE_Bookings();






add_action( 'woocommerce_add_order_item_meta', 'add_order_item_meta' , 10, 2);
function add_order_item_meta ( $item_id, $values ) {
    if ( isset( $values [ 'booking_start_date' ] ) ) {
        $custom_data  = $values [ 'booking_start_date' ];
        wc_add_order_item_meta( $item_id, ‘date',           
        $custom_data['booking_start_date'] );
    }
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

2 Answers2

1

You don't need to add any custom meta data to the order, as you can retrieve it easily (as you are expecting).

You will see in the following code example that displays the start date, the start time, the End date and the End time in admin single orders below shipping address:

add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_some_booking_data_to_admin_orders', 10, 1 );
function display_some_booking_data_to_admin_orders( $order ){
    // Retreive the booking Ids that belong to an order
    $bookings_ids = get_posts( array(
        'posts_per_page' => -1,
        'post_type'      => 'wc_booking', // booking post type
        'post_parent'    => $order->get_id(),
        'post_status'    => 'all',
        'fields'         => 'ids',
    ) );

    if( ! empty($bookings_ids) ) {
        echo '<div class="booking-items">';

        // Loop through Bookings for the current order
        foreach ( $bookings_ids as $booking_id ) {
            // Get an instance of the WC_Booking Object
            $booking = new WC_Booking( $booking_id );

            // Get the related instance of the order Item Object
            $item = $order->get_item($booking->order_item_id);

            $name = $item->get_name(); // Get product name

            // Start date and time
            $start_datetime = $booking->get_start_date();
            $start_dt_array = explode(', ', $start_datetime);
            $start_date     = reset($start_dt_array); // Start date
            $start_time     = end($start_dt_array); // Start time

            // End date and time
            $end_datetime   = $booking->get_end_date();
            $end_dt_array   = explode(', ', $end_datetime);
            $end_date       = reset($end_dt_array); // End date
            $end_time       = end($end_dt_array); // End time

            echo '<table style="border:solid 1px #eee; margin-bottom:12px;">
                <thead style="background-color: #eee;">
                    <tr><td><strong>' . __("Booking") . ':</strong></td><td> ' . $name . ' <em><small>(' . $booking_id . ')</small></em></td></tr>
                </thead>
                <tbody>
                    <tr><td><strong>' . __("Start date") . ':</strong></td><td>' . $start_datetime . '</td></tr>
                    <tr><td><strong>' . __("End date")   . ':</strong></td><td>' . $end_datetime   . '</td></tr>
                </tbody>
            </table>';
        }
        echo '</div>';
    }
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

enter image description here


Addition for Exporting order data

Save booking data as custom order meta data (only handle one booking):

add_action( 'woocommerce_checkout_create_order', 'display_some_booking_data_to_admin_orders', 10, 1 );
function display_some_booking_data_to_admin_orders( $order ){
    $cart_items = WC()->cart->get_cart(); // Get cart items
    $cart_item  = reset($cart_item); // First cart item

    if( isset($cart_item['booking']) && ! empty($cart_item['booking']) ) {
        $booking_id = $cart_item['booking']['_booking_id'];

        $order->update_meta_data( '_booking_id', $booking_id ); // Save booking Id

        // Get an instance of the WC_Booking Object
        $booking = new WC_Booking( $cart_item['booking']['_booking_id'] );

        // Start date and time
        $start_datetime = $booking->get_start_date();
        $start_dt_array = explode(', ', $start_datetime);

        $order->update_meta_data( 'booking_start_datetime', $start_datetime ); // Save start date and time
        $order->update_meta_data( 'booking_start_date', reset($start_dt_array) ); // Save start date
        $order->update_meta_data( 'booking_start_time', end($start_dt_array) ); // Save start time

        // End date and time
        $end_datetime   = $booking->get_end_date();
        $end_dt_array   = explode(', ', $end_datetime);

        $order->update_meta_data( 'booking_end_datetime', $end_datetime ); // Save end date and time
        $order->update_meta_data( 'booking_end_date', reset($end_dt_array) ); // Save end date
        $order->update_meta_data( 'booking_end_time', end($end_dt_array) ); // Save end time

        // Cost and quantiity
        $order->update_meta_data( 'booking_cost', $cart_item['booking']['_cost'] ); // Save cost
        $order->update_meta_data( 'booking_qty', $cart_item['booking']['_qty'] ); // Save quantity
    }
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

This will allow you to export the booking data with your plugin.

halfer
  • 19,824
  • 17
  • 99
  • 186
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Him, thank you for the help with this, but Im really needing it to go into the the custom meta data, this is because Im using the plugin Advanced Order Export For WooCommerce (Pro), and I need this data to go into the meta data field so I can then use it to filter order. For example I want to be able to export order that only have todays start date etc. I hope that makes better sense now – Alasdair MacEwan Feb 09 '21 at 14:16
  • Hi, to be honest Im not sure I fully understand your comment. I understand that it should be set as order item meta data. Yes the plugin handles order item meta data and this is why i need it to be created so the export plugin is able to handle it and identify it, so when we export, it come out properly. Im not sure what type of code is best to be honest as the code would need to know that an order might have 2 dates in it and like those dates and start/end times to the correct product. Its a bit messy, thank you for your help with this, I do really appreciate it – Alasdair MacEwan Feb 09 '21 at 14:45
  • Ok thanks, then I can add them separately and just give it an overview so that other people with the issue can see the pros and cons of each. I do really appreciate your help. Thank you again – Alasdair MacEwan Feb 09 '21 at 15:21
  • hi, thank you again for the help, to understand this a little more am I amble to put it into a loop where it would if there is two booking it would add them to the custom field order meta data, so for instance if the order contained 2 bookings it booking 1 started date in and then relate this to the start time 1 and then end date 1 and end time 1, 1 relating it being the first booking in that order, then it would create another meta data field for booking 2, for its start time, then another field for the second bookings start date, end date etc. – Alasdair MacEwan Feb 09 '21 at 21:27
  • then it could pick this up no matter how many booking there are in any single order. I would just need to add the additional fields to the export, so it knows to look for start_date1 & start_date2 & start_date3 etc This could then make it more able to pick up on all the booking data etc, to put this loop in place we would need to add a loop function at the start of the code and then loop it for each part of the booking data like the start date, start time, end date and end time?? – Alasdair MacEwan Feb 09 '21 at 21:27
  • Sorry, so Ive tried to add second set of code and I cant seem to get it to work, firstly the function name is the same as the function name in the first code so I cant use them together, but when ive tried to just run the second set of code youve add, the custom order meta data doesnt appear on the order page for some reason. Ive tried it just with 1 booking in the cart and then tried it with 2 and Im not sure if its working, i added it via the snippets plugin. thanks – Alasdair MacEwan Feb 09 '21 at 21:35
  • Ive tried running just the first set of code and it works beautifully, thank you but just not the second set of code – Alasdair MacEwan Feb 09 '21 at 21:42
  • @AlasdairMacEwan Because you can't use the same keys for a 2nd one. So that is the problem as booking data is related to order items… – LoicTheAztec Feb 09 '21 at 21:49
  • okay, I understand that, but in theory, a loop could be added? to create new meta dat fields for each bit of information for each booking, so it would create a custom field for booking 1 for its start date...etc then it would create another custom for the rest of the data, then once it has processed the 1st booking on that order, it would then process the next booking creating a second custom field for the start date of the second booking and then again for all other other bits of data? sorry for all the questions, Im just wanting to learn and understand as I go and if this can happen, thanks – Alasdair MacEwan Feb 09 '21 at 22:36
0

Please, use this solution to filter by start date https://wordpress.org/support/topic/filter-by-bookings-start-date/#post-12908495

if you still need help - please, submit ticket to https://algolplus.freshdesk.com/

thanks, Alex (support of Advanced Order Export For WooCommerce)

alexv66
  • 16
  • 2