2

I found the following solution in another answer to a similar question: Add text to order summary based on a custom field value in WooCommerce. I have two pickup locations (and a third to be added next year only).

I managed to implement the code from the solution on my staging server but I have an issue with the INFO data because each location has different opening hours. So how do I make sure this difference gets added to the order data and email and display the correct hours for the location selected?

Here's what my code looks like:

    // WC CHECKOUT PAGE: Add pickup location seletion on checkout page
add_filter( 'woocommerce_checkout_fields' , 'custom_store_pickup_field');
function custom_store_pickup_field( $fields ) {
    $fields['billing']['store_pickup'] = array(
        'type'     => 'select',
        'id'       => 'store_pickup_val',
        'label'    => __('For pickup, select a pickup location (Optional)', 'woocommerce'),
        'required' => true,
        'class'    => array('store-pickup form-row-wide'),
        'options'  => array(
            ''=> 'select a pickup location',
            'option_1' => 'Crossroads Farmers’ Market',
            'option_2' => 'Market on Macleod',
            'option_3' => '',
        ),
        'clear'     => true,
    );
    return $fields;
}

//* Process the checkout
add_action('woocommerce_checkout_process',  'wps_select_checkout_field_process');
function wps_select_checkout_field_process() {
    // Check if set, if its not set add an error.
    if ( $_POST['store_pickup'] == "option_0" )
        wc_add_notice( '<strong>Please select a pickup location</strong>', 'error' );
}

// Add opening hours for each location
add_action( 'woocommerce_after_checkout_form', 'shop_opening_hours', 6 );
function shop_opening_hours() {
     ?>
    <script type="text/javascript">
        (function($){
            $('#store_pickup_val').change( function(){
                $( ".shop-collection" ).remove();
                if (this.value == 'option_0') {
                    $('#shipping_method_0_flat_rate1').prop('checked', true);
                } else if (this.value == 'option_1') {
                     $( "<p>Order can be picked up between 9am - 5pm on Friday-Sunday</p>" ).addClass("shop-collection").insertAfter( "#store_pickup_val" );
                     $('#shipping_method_0_local_pickup3').prop('checked', true);
                } else if (this.value == 'option_2') {
                    $( "<p>Order can be picked up between 9pm - 5pm on Thursday-Sunday</p>" ).addClass("shop-collection").insertAfter( "#store_pickup_val" );
                    $('#shipping_method_0_local_pickup3').prop('checked', true);
                }
                $('body').trigger('update_checkout');
            });
        })(jQuery);
    </script>
<?php
}

// Now save the pickup location data to the order meta
add_action( 'woocommerce_checkout_update_order_meta', 'store_pickup_field_update_order_meta', 10, 1 );
function store_pickup_field_update_order_meta( $order_id ) {

    // BELOW update the data
    if ( $_POST['store_pickup'] == 'option_1' )
        $data = array( 
            'location' => 'Crossroads Farmers’ Market', 
            'address' => '1235 26 Avenue SW<br> Calgary, Alberta<br> T2G 1R7' 
        );
    elseif ( $_POST['store_pickup'] == 'option_2' )
        $data = array( 
        'location' => 'Market on Macleod', 
        'address' => '7711 Macleod Trail S<br> Calgary, Alberta<br> T2H 0M1' 
    );


    $collect_info = 'Order can be picked up between 9:00am - 5:00pm on Friday-Sunday';

    if ( $_POST['store_pickup'] == 'option_1' || $_POST['store_pickup'] == 'option_2' ){
        // HTML
        $store_pickup = "<h3>Pickup Information</h3>
        <table class='pickup td' cellspacing='0' cellpadding='6'>
            <tr>
                <th>Location:</th>
                <td>".$data['location']."</td>
            </tr>
            <tr>
                <th><strong>Adress:</strong></th>
                <td>".$data['address']."</td>
            </tr>
            <tr>
                <th><strong>Info:</strong></th>
                <td>".$collect_info."</td>
            </tr>
        </table>";

        // Save pickup html data (front end)
        update_post_meta( $order_id, '_store_pickup_data', $store_pickup );
        // Save pickup location (backend)
        update_post_meta( $order_id, '_store_pickup_location', $data['location'] );
    }
}

// Display 'pickup location' on the order edit page (backend)
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_store_pickup_location_on_order_edit_pages', 10, 1 );
function display_store_pickup_location_on_order_edit_pages( $order ){
    $pickup_location = get_post_meta( $order->get_id(), '_store_pickup_location', true );
    if( ! empty( $pickup_location ) )
        echo '<p><strong>Store pickup location: </strong> ' . $pickup_location . '</p>';
}

// Display 'pickup html data' in "Order received" and "Order view" pages (frontend)
add_action( 'woocommerce_order_details_after_order_table', 'display_store_pickup_data_in_orders', 10 );
function display_store_pickup_data_in_orders( $order ) {
    $pickup_data = get_post_meta( $order->get_id(), '_store_pickup_data', true );
    if( ! empty( $pickup_data ) )
        echo $pickup_data;
}

// Display 'pickup html data' in Email notifications (frontend)
add_action( 'woocommerce_email_order_meta', 'display_store_pickup_data_in_emails', 10 );
function display_store_pickup_data_in_emails( $order ) {
    $pickup_data = get_post_meta( $order->get_id(), '_store_pickup_data', true );
    if( ! empty( $pickup_data ) ){
        // Email CSS style rules
        echo '<style>
        table.pickup{width: 100%; font-family: \'Helvetica Neue\', Helvetica, Roboto, Arial, sans-serif;
            color: #737373; border: 1px solid #e4e4e4;}
        table.pickup th, table.pickup td{text-align: left; border-top-width: 4px;
            color: #737373; border: 1px solid #e4e4e4; padding: 12px;}
        table.pickup td{text-align: left; border-top-width: 4px; color: #737373; border: 1px solid #e4e4e4; padding: 12px;}
        </style>';
        // Html data
        echo $pickup_data;
    }

}

Any help would be greatly appreciated Lyse

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Lyse
  • 53
  • 1
  • 8

1 Answers1

3

Updated: You just forgot to add different "info" for each pickup location:

// Now save the pickup location data to the order meta
add_action( 'woocommerce_checkout_update_order_meta', 'store_pickup_field_update_order_meta', 10, 1 );
function store_pickup_field_update_order_meta( $order_id ) {
    // Only for chosen "option_1" and "option_2"
    if ( $_POST['store_pickup'] == 'option_1' || $_POST['store_pickup'] == 'option_2' ){

        // 1. Set the data in an array, conditionally on chosen option value

        $collect_info = __('Order can be picked up between ');
        if( $_POST['store_pickup'] == 'option_1' ){
            $data = array(
                'location' => __('Crossroads Farmers’ Market'),
                'address'  => __('1235 26 Avenue SW<br> Calgary, Alberta<br> T2G 1R7'),
                'info'     => $collect_info . __('9:00am - 5:00pm on Friday-Sunday')
            );
        } else {
            $data = array( 
                'location' => __('Market on Macleod'),
                'address'  => __('7711 Macleod Trail S<br> Calgary, Alberta<br> T2H 0M1'),
                'info'     => $collect_info . __('9:00am - 5:00pm on Thursday-Sunday')
            );
        }

        // 2. Set the data in a formatted HTML string

        $data_html = "<h3>Pickup Information</h3>
        <table class='pickup td' cellspacing='0' cellpadding='6'>
            <tr>
                <th>Location:</th>
                <td>".$data['location']."</td>
            </tr>
            <tr>
                <th><strong>Adress:</strong></th>
                <td>".$data['address']."</td>
            </tr>
            <tr>
                <th><strong>Info:</strong></th>
                <td>".$data['info']."</td>
            </tr>
        </table><br>";

        // 3. Save the data to the Order meta data

        // Pickup html formated data
        update_post_meta( $order_id, '_store_pickup_data', $data_html );

        // Pickup location
        update_post_meta( $order_id, '_store_pickup_location', $data['location'] );
    }
}

Also your jQuery code can be simplified a bit:

// Add opening hours for each location
add_action( 'woocommerce_after_checkout_form', 'shop_opening_hours', 6 );
function shop_opening_hours() {
     ?>
    <script type="text/javascript">
        (function($){
            $('#store_pickup_val').change( function(){
                $( ".shop-collection" ).remove();
                if (this.value == 'option_1') {
                    $( "<p>Order can be picked up between 9am - 5pm on Friday-Sunday</p>" ).addClass("shop-collection").insertAfter( "#store_pickup_val" );
                    $('#shipping_method_0_local_pickup3').prop('checked', true);
                } else if (this.value == 'option_2') {
                    $( "<p>Order can be picked up between 9pm - 5pm on Thursday-Sunday</p>" ).addClass("shop-collection").insertAfter( "#store_pickup_val" );
                    $('#shipping_method_0_local_pickup3').prop('checked', true);
                } else {
                    $('#shipping_method_0_flat_rate1').prop('checked', true);
                }
                $('body').trigger('update_checkout');
            });
        })(jQuery);
    </script>
<?php
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.


Tested and works.You will get:

For "option_1" in Order received / view order pages | Email notifications

enter image description here

For "option_2" in Order received / view order pages | Email notifications

enter image description here


An advice:
In the first code function (at the end) instead of saving only the pickup location (non formatted data), you could save all the non formatted data in an array this way:

 // Save all Pickup non formatted data array  
 update_post_meta( $order_id, '_store_pickup', $data );

So to access this data, you will simply use:

 $data = get_post_meta( $order_id, '_store_pickup', true );

 $pickup_location = $data['location'];
 $pickup_address  = $data['address'];
 $pickup_info     = $data['info'];

This way you are sure to save in the order an accessible non formatted complete pickup data.

In this case, this could replace:

$pickup_location = get_post_meta( $order->get_id(), '_store_pickup_location', true );

Using instead:

$pickup_location = get_post_meta( $order->get_id(), '_store_pickup', true )['location'];

So you could remove definitively Pickup location saving function…

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • I have replaced the code as you suggested but the account data and order emails not longer display the pickup location information. – Lyse Nov 17 '17 at 17:14
  • Loic, I see the pickup location in the account and email now but when I select option 2, Macleod location, it's option 1 data that gets selected in the order, account, and email. – Lyse Nov 17 '17 at 18:11
  • I never get to see the Macleod location being picked up as a location in the data elements. – Lyse Nov 17 '17 at 18:17
  • I updated the data array for location 1 and location 2 like it was before and all the outstanding issues got resolved. The code looks like this now: – Lyse Nov 17 '17 at 19:04
  • Here what I added: // Set the data in an array if ( $_POST['store_pickup'] == 'option_1' ) $data = array( 'location' => __('Crossroads Farmers’ Market'), 'address' => __('1235 26 Avenue SW
    Calgary, Alberta
    T2G 1R7'), 'info' => $collect_info ); elseif ( $_POST['store_pickup'] == 'option_2' ) $data = array( 'location' => __('Market on Macleod'), 'address' => __('7711 Macleod Trail S
    Calgary, Alberta
    T2H 0M1'), 'info' => $collect_info );
    – Lyse Nov 17 '17 at 19:08
  • @Lyse Really sorry I am a bit tired today and it was complicate to make tests with your shipping setting… **I have make a functional update.**… Also you didn't answer my comment in the other question where I have answered some days ago. You removed my accepted answer checkmark. Can I know why please?… may be it's a wrong manipulation. – LoicTheAztec Nov 17 '17 at 23:10
  • I'm sorry but it was an editing error on my part. Thank you for your advice, but all is working perfectly now so I did not try to implement your advice component of the solution (I also was not sure exactly where to put the code.) You've been a great help at finding a working solution and I'm very happy. – Lyse Nov 17 '17 at 23:35
  • Using this example, would it be difficult to add a shipping insurance option on the checkout page in a similar way, (yes or no option) and if yes, add a 2.5% additional fee to the total order amount? – Lyse Feb 28 '19 at 23:45
  • @Lyse You have some other examples that you can use like [this thread](https://stackoverflow.com/a/51572051/3730754) or [this other](https://stackoverflow.com/a/49470265/3730754)… You can adapt the code to get what you want. – LoicTheAztec Mar 01 '19 at 00:12
  • But this additional insurance fee calculation should be offered as an option to the customer during checkout. I also noticed that the code adds a flat fee, would it work for calculating a % fee in the same way? – Lyse Mar 01 '19 at 00:58
  • Is it possible to save the selected pickup location to client's profile so it is pre-loading on future purchases? Like it's name, address etc. – Nikolas Aug 14 '22 at 12:17