phpwordpressdatetimewoocommercefee

How to add order fee based on Select Delivery Date woo commerce checkout?


I am using xdsoft date time picker at woo-commerce checkout and need to add an extra fee if a user selects the same day or tomorrow on the date time picker. I am not sure how to go with this and would appreciate it if someone can help me with this.

Below is the code I am using currently and it is working fine for the situation.

function date_time_picker( $checkout ) {
    woocommerce_form_field( 'delivery_date', array(
        'type'          => 'text',
        'class'         => array('form-row-wide'),
        'id'            => 'datepicker',
        'required'      => true,
        'label'         => __('Select Delivery Date'),
        'placeholder'       => __('Click to select date'),
    )); 
}
add_action( 'woocommerce_after_order_notes', 'date_time_picker' );   
  
function validate_new_checkout_fields() {   
   if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) wc_add_notice( __( 'Please select the Delivery Date' ), 'error' );
}
add_action( 'woocommerce_checkout_process', 'validate_new_checkout_fields' );

function enable_datepicker() { 
    ?>
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>   
    <?php       
}
add_action( 'woocommerce_after_checkout_form', 'enable_datepicker', 10 );

function load_calendar_dates( $available_gateways ) {
   ?>
   <script type="text/javascript">
  
      jQuery(document).ready(function($) {

        jQuery.datetimepicker.setLocale('en');

        var currentDate = new Date();
        var minutes = currentDate.getMinutes();
        var m = (Math.ceil(minutes/30) * 30) % 60;
        currentDate.setMinutes(m);          

        jQuery('#datepicker').datetimepicker({
            beforeShowDay: $.datepicker.noWeekends,
            format: 'Y/m/d H:i:s',
            minDate: 0,             
            minTime: '8:00',
            step: "30",
             allowTimes:[
              '09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30',
              '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
             ]              
        });         
  
      });
  
   </script>
   <?php
   
}
add_action( 'woocommerce_after_checkout_form', 'load_calendar_dates', 20 );

Solution

  • You can use woocommerce_cart_calculate_fees to add fees.

    Use add_fee() function to add fees. You need to calculate datediff for today and tomorrow day. furthermore, you can see PHP: How to check if a date is a today, yesterday or tomorrow Try the below code.

    /**
     * Add a standard $ value surcharge to all transactions in cart/checkout
     */
    function wc_add_surcharge() { 
        global $woocommerce; 
    
        if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
            return;
        }
        
        // change the $fee to set the surcharge to a value to suit
        parse_str($_POST['post_data'], $post_data);
    
        if( isset( $post_data['delivery_date'] ) && $post_data['delivery_date'] != '' ){
    
            $current = strtotime(date("Y-m-d"));
            $date    = strtotime($post_data['delivery_date']);
    
            $datediff = $date - $current;
            $difference = floor($datediff/(60*60*24));
            if( $difference == 0 || $difference == 1 ){
                $fee = 5.00; // today and tomorrow
                $woocommerce->cart->add_fee( 'Fast delivery charge', $fee, true, 'standard' );  
            } else {
                // other day
                $fees = WC()->cart->get_fees();
                foreach ($fees as $key => $fee) {
                    if($fees[$key]->name === __( "Fast delivery charge")) {
                        unset($fees[$key]);
                    }
                }
                WC()->cart->fees_api()->set_fees($fees);
            } 
        }
        
    }
    add_action( 'woocommerce_cart_calculate_fees','wc_add_surcharge' ); 
      
    function date_time_picker( $checkout ) { 
        woocommerce_form_field( 'delivery_date', array(
            'type'          => 'text',
            'class'         => array('form-row-wide'),
            'id'            => 'datepicker',
            'required'      => true,
            'label'         => __('Select Delivery Date'),
            'placeholder'       => __('Click to select date'),
        ));    
    }
    add_action( 'woocommerce_after_order_notes', 'date_time_picker' );
       
    function validate_new_checkout_fields() {       
        if ( isset( $_POST['delivery_date'] ) && empty( $_POST['delivery_date'] ) ) wc_add_notice( __( 'Please select the Delivery Date' ), 'error' ); 
    }
    add_action( 'woocommerce_checkout_process', 'validate_new_checkout_fields' );
      
    

    In datetimepicker You can use onSelectDate and onSelectTime event to trigger update_checkout

    function load_calendar_dates( $available_gateways ) {
       ?>
        <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-datetimepicker/2.5.20/jquery.datetimepicker.full.min.js"></script>    
        <script type="text/javascript">
      
            jQuery(document).ready(function($) {
    
                jQuery.datetimepicker.setLocale('en');
    
                var currentDate = new Date();
                var minutes = currentDate.getMinutes();
                var m = (Math.ceil(minutes/30) * 30) % 60;
                currentDate.setMinutes(m);          
    
                jQuery('#datepicker').datetimepicker({
                    beforeShowDay: $.datepicker.noWeekends,
                    format: 'Y/m/d H:i:s',
                    minDate: 0,             
                    minTime: '8:00',
                    step: "30",
                    allowTimes:[
                        '09:00', '09:30', '10:00', '10:30', '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', '14:30', '15:00', '15:30', '16:00', '16:30', '17:00'
                    ],onSelectDate:function(ct,$i){
                        $( 'body' ).trigger( 'update_checkout' );
                     
                    },onSelectTime:function(ct,$i){
                        $( 'body' ).trigger( 'update_checkout' );
                    }             
                });
    
            });
      
       </script>
       <?php 
    }
    add_action( 'woocommerce_after_checkout_form', 'load_calendar_dates', 20 );
    

    Save Select Delivery Date and show in Order edit page and emails.

    function save_delivery_date_field( $order_id ) { 
        if ( $_POST['delivery_date'] ) update_post_meta( $order_id, 'delivery_date', esc_attr( $_POST['delivery_date'] ) );
    }  
    add_action( 'woocommerce_checkout_update_order_meta', 'save_delivery_date_field' );
      
    function show_delivery_date_field_order( $order ) {    
       $order_id = $order->get_id();
       if ( get_post_meta( $order_id, 'delivery_date', true ) ) echo '<p><strong>Delivery Date:</strong> ' . get_post_meta( $order_id, 'delivery_date', true ) . '</p>';
    }
    add_action( 'woocommerce_admin_order_data_after_billing_address', 'show_delivery_date_field_order', 10, 1 );
     
    function show_delivery_date_field_emails( $order, $sent_to_admin, $plain_text, $email ) {
        if ( get_post_meta( $order->get_id(), 'delivery_date', true ) ) echo '<p><strong>Delivery Date:</strong> ' . get_post_meta( $order->get_id(), 'delivery_date', true ) . '</p>';
    }
    add_action( 'woocommerce_email_after_order_table', 'show_delivery_date_field_emails', 20, 4 );