1

On purchase/checkout of an item(s) via Woocommerce, My checkout code includes 2 hidden fields that sends default post meta value saved under _dispatch and _dispatch_driver.

This post meta feeds a select field with the first values in the admin side of order item.

I have custom post types with information that should feed the select options fields as the other options.

My issues are on the admin side when the order item is opened.

  1. The default information is set well but I can seem to save/change the second select field on clicking the update button.
  2. I can not feed the woocommerce options fields with my values from the CPT queries I have done.

Code made partially from: Custom editable field in Woocommerce admin edit order pages general section

add_action( 'woocommerce_checkout_update_order_meta', 'save_custom_checkout_field'), 10, 1 );
add_action('woocommerce_admin_order_data_after_order_details', 'editable_order_custom_field', 10, 1 );
add_action( 'woocommerce_process_shop_order_meta', 'save_order_custom_field_meta_data', 12, 2 );

//Then you will need to save this hidden field in the order, this way:

function save_custom_checkout_field( $order_id ) {

    if ( ! empty( $_POST['dispatch'] ) )
        update_post_meta( $order_id, '_dispatch', sanitize_text_field( $_POST['dispatch'] ) );

    if ( ! empty( $_POST['dispatch_driver'] ) )
        update_post_meta( $order_id, '_dispatch_driver', sanitize_text_field( $_POST['dispatch_driver'] ) );

}
// Output a custom editable field in backend edit order pages under general section
function editable_order_custom_field( $order ){
    // Loop through order items

    foreach( $order->get_items() as $item_id => $item ){
        // Get "customer reference" from order item meta data
        if( $item->get_meta('_dispatch') ){
            // The "customer reference"
            $item_value = $item->get_meta('_dispatch');

            // We output a hidden field with the Item ID (to be able to update this order item meta data later)
            echo '<input type="hidden" name="item_id" value="' . $item_id . '">';

            break; // We stop the loop
        }

        if( $item->get_meta('_dispatch_driver') ){
            // The "customer reference"
            $item_value_ref = $item->get_meta('_dispatch_driver');

            // We output a hidden field with the Item ID (to be able to update this order item meta data later)
            echo '<input type="hidden" name="item_id_ref" value="' . $item_value_ref . '">';

            break; // We stop the loop
        }
    }

    // Get "customer reference" from meta data (not item meta data)
    $dispatch_updated_value = $order->get_meta('_dispatch');
    $dispatch_driver_updated_value = $order->get_meta('_dispatch_driver');

    // Replace "dispatch reference" value by the meta data if it exist
    $dispatch_new_value = $dispatch_updated_value ? $dispatch_updated_value : ( isset($item_value) ? $item_value : '');
    $dispatch_driver_new_value = $dispatch_driver_updated_value ? $dispatch_driver_updated_value : ( isset($item_value_ref) ? $item_value_ref : '');

    $variable = $data_dispatches )[0];

    // Display the custom editable field
    woocommerce_wp_select( array(
        'id'            => 'dispatch',
        'label'         => __("Dispatch Reference:", "woocommerce"),
        'type'          => 'select',
        'options'       => array (
            //$variable
            $dispatch_new_value   => __( $dispatch_new_value, 'woocommerce' ),
            'Unassigned'  => __('Unassigned', 'woocommerce' ),
            'nagulu'    => __('Nagulu', 'woocommerce' ),
            'kamwokya'  => __('Kamwokya', 'woocommerce' ),
            'bukoto'    => __('Bukoto', 'woocommerce' )
            )
    ) );

    woocommerce_wp_select( array(
        'id'            => 'dispatch-driver',
        'label'         => __("Dispatch Driver:", "woocommerce"),
        'type'          => 'select',
        'options'       => array (  
            $dispatch_driver_new_value   => __( $dispatch_driver_new_value, 'woocommerce' ),
            'Unassigned'  => __('Unassigned', 'woocommerce' ),
            'kamwokya'  => __('Kamwokya', 'woocommerce' ),
            'bukoto'    => __('Bukoto', 'woocommerce' )
        ),
    ) );
}

// Save the custom editable field value as order meta data and update order item meta data
function save_order_custom_field_meta_data( $post_id, $post ){

    if( isset( $_POST[ 'dispatch' ] ) ){
        // Save "dispatch reference" as order meta data
        update_post_meta( $post_id, '_dispatch', sanitize_text_field( $_POST[ 'dispatch' ] ) );

        // Update the existing "dispatch reference" item meta data
        if( isset( $_POST[ 'item_id' ] ) )
            wc_update_order_item_meta( $_POST[ 'item_id' ], 'Dispatch No.', $_POST[ 'dispatch' ] );
    }

    if( isset( $_POST[ 'dispatch_driver' ] ) ){
        // Save "dispatch_driver reference" as order meta data
        update_post_meta( $post_id, '_dispatch_driver', sanitize_text_field( $_POST[ 'dispatch_driver' ] ) );

        // Update the existing "dispatch_driver reference" item meta data
        if( isset( $_POST[ 'item_id_ref' ] ) )
            wc_update_order_item_meta( $_POST[ 'item_id_ref' ], 'Dispatch Driver', $_POST[ 'dispatch_driver' ] );
    }
}     
}

This is the code for saving the initial details in checkout phase

function register() {
    add_action( 'woocommerce_after_order_notes', array( $this, 'my_custom_checkout_field' ), 10, 1 );
    add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'save_custom_checkout_field'), 10, 1 );
}

//Then you will need to save this hidden field in the order, this way:
function my_custom_checkout_field( $checkout ) {

    $dispatch = 'Unassigned Dispatch No';
    $dispatch_driver = 'Unassigned Driver';

    // Output the hidden link
    echo '
        <div id="dispatch_checkout_field">
                <input type="hidden" class="input-hidden" name="dispatch" id="dispatch" value="' . $dispatch . '">
        </div>
        <div id="dispatch_driver_checkout_field">
                <input type="hidden" class="input-hidden" name="dispatch_driver" id="dispatch_driver" value="' . $dispatch_driver . '">
        </div>
    ';
}

//Then you will need to save this hidden field in the order, this way:

function save_custom_checkout_field( $order_id ) {

    if ( ! empty( $_POST['dispatch'] ) )
        update_post_meta( $order_id, '_dispatch', sanitize_text_field( $_POST['dispatch'] ) );

    if ( ! empty( $_POST['dispatch_driver'] ) )
        update_post_meta( $order_id, '_dispatch_driver', sanitize_text_field( $_POST['dispatch_driver'] ) );

}
omukiguy
  • 1,401
  • 3
  • 17
  • 36

1 Answers1

1

As your checkout fields are hidden fields with always the same values, you don't need them. You just need to save them dirrectly as order meta data with an 'unassigned' value for both. Now for that there is a better hook:

add_action( 'woocommerce_checkout_create_order', 'save_custom_checkout_field', 10, 2 );
function save_custom_checkout_field( $order, $data ) {
    $order->update_meta_data( '_dispatch', 'unassigned' );
    $order->update_meta_data( '_dispatch_driver', 'unassigned' );
}

Now your 2nd select field is not being saved as there is a mistake in the select field slug… I have removed also all the unneeded code and made some changes:

// Output a custom editable field in backend edit order pages under general section
add_action('woocommerce_admin_order_data_after_order_details', 'editable_order_custom_field', 10, 1 );
function editable_order_custom_field( $order ){
    // Display the custom editable field
    woocommerce_wp_select( array(
        'id'            => '_dispatch',
        'label'         => __("Dispatch Reference:", "woocommerce"),
        'type'          => 'select',
        'options'       => array (
            'unassigned'    => __('Unassigned Dispatch No', 'woocommerce' ),
            'nagulu'        => __('Nagulu', 'woocommerce' ),
            'kamwokya'      => __('Kamwokya', 'woocommerce' ),
            'bukoto'        => __('Bukoto', 'woocommerce' )
        ),
    ) );

    woocommerce_wp_select( array(
        'id'            => '_dispatch_driver',
        'label'         => __("Dispatch Driver:", "woocommerce"),
        'type'          => 'select',
        'options'       => array (
            'unassigned'    => __('Unassigned Driver', 'woocommerce' ),
            'kamwokya'      => __('Kamwokya', 'woocommerce' ),
            'bukoto'        => __('Bukoto', 'woocommerce' )
        ),
    ) );
}

// Save the custom editable field value as order meta data and update order item meta data
add_action( 'woocommerce_process_shop_order_meta', 'save_order_custom_field_meta_data', 12, 2 );
function save_order_custom_field_meta_data( $post_id, $post ){
    if( isset( $_POST[ '_dispatch' ] ) ){
        update_post_meta( $post_id, '_dispatch', esc_attr( $_POST[ '_dispatch' ] ) );
    }
    if( isset( $_POST[ '_dispatch_driver' ] ) ){
        update_post_meta( $post_id, '_dispatch_driver', esc_attr( $_POST[ '_dispatch_driver' ] ) );
    }
}

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

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399