Load user custom data on WooCommerce admin new order custom fields

Viewed 741

Inspired by Woocommerce editable custom checkout field and in get_formatted_shipping_address answer code, I have been able to add 2 new billing and shipping fields, with the following code:

// Checkout and my account (add) unit number and floor number
add_filter( 'woocommerce_billing_fields' , 'custom_field_billing_extra' );
function custom_field_billing_extra( $fields ) {
    $fields['billing_house_number'] = array(
        'type' => 'text', // chose the field type
        //'label' =>  __('Custom label (billing)',  'woocommerce' ),
        'class' => array('form-row-first my-custom-class'), // can be also 'form-row-first' or 'form-row-last'
        'required' => false, // Optional
        'clear' => true, // Optional
        'priority' => 61, // To change the field location increase or decrease this value
        'placeholder' => __('Unit number', 'custom-domain'),
    );
    /////////////////////////////
    
        $fields['billing_floor_number'] = array(
        'type' => 'text', // chose the field type
        //'label' =>  __('Custom label (billing)',  'woocommerce' ),
        'class' => array('form-row-last my-custom-class'), // can be also 'form-row-first' or 'form-row-last'
        'required' => false, // Optional
        'clear' => true, // Optional
        'priority' => 61, // To change the field location increase or decrease this value
        'placeholder' => __('Floor number', 'custom-domain'),
    );
    return $fields;
}


add_filter( 'woocommerce_shipping_fields' , 'custom_field_shipping_extra' );
function custom_field_shipping_extra( $fields ) {
    $fields['shipping_house_number'] = array(
        'type' => 'text', // chose the field type
        //'label' =>  __('Custom label (billing)',  'woocommerce' ),
        'class' => array('form-row-first my-custom-class'), // can be also 'form-row-first' or 'form-row-last'
        'required' => false, // Optional
        'clear' => true, // Optional
        'priority' => 61, // To change the field location increase or decrease this value
        'placeholder' => __('Unit number', 'custom-domain'),
    );
    /////////////////////////////
        $fields['shipping_floor_number'] = array(
        'type' => 'text', // chose the field type
        //'label' =>  __('Custom label (billing)',  'woocommerce' ),
        'class' => array('form-row-last my-custom-class'), // can be also 'form-row-first' or 'form-row-last'
        'required' => false, // Optional
        'clear' => true, // Optional
        'priority' => 61, // To change the field location increase or decrease this value
        'placeholder' => __('Floor number', 'custom-domain'),
    );
    return $fields;
}

// Admin editable single orders shipping and billing new fields
add_filter( 'woocommerce_admin_billing_fields' , 'admin_order_page_new_fields' );
add_filter( 'woocommerce_admin_shipping_fields' , 'admin_order_page_new_fields' );
function admin_order_page_new_fields( $fields ) {
    // Include shipping phone as editable field
    $fields['house_number'] = array( 'label' => __('House Number', 'custom-domain'), 'show' => '0' );
    
    $fields['floor_number'] = array( 'label' => __('floor Number', 'custom-domain'), 'show' => '0' );

    return $fields;
}


// Admin editable User shipping new fields
add_filter( 'woocommerce_customer_meta_fields', 'user_new_field_account' );
function user_new_field_account( $fields ) {
    $fields['billing']['fields']['house_number'][type]  = $fields['shipping']['fields']['house_number'][type]  ='text';
    $fields['billing']['fields']['house_number'][label]  = $fields['shipping']['fields']['house_number'][label]  = __('House Number', 'custom-domain');
    $fields['billing']['fields']['house_number'][description]  = $fields['shipping']['fields']['house_number'][description]  = 'House Number';
    
        $fields['billing']['fields']['floor_number'][type]  = $fields['shipping']['fields']['floor_number'][type]  ='text';
    $fields['billing']['fields']['floor_number'][label]  = $fields['shipping']['fields']['floor_number'][label]  = __('Floor Number', 'custom-domain');
    $fields['billing']['fields']['floor_number'][description]  = $fields['shipping']['fields']['floor_number'][description]  = 'Floor Number';

    return $fields;
}

// add the custom fields to email
add_action('woocommerce_email_customer_details','add_house_number_field_to_emails_notifications', 19, 4 );
function add_house_number_field_to_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {

    $output = '';
    $shipping_house_number = get_post_meta( $order->id, '_shipping_house_number', true );

    if ( !empty($shipping_house_number) )
        $output .= '<div><strong>' . __('House Number:', 'custom-domain') . '</strong> <span class="text">' . $shipping_house_number . '</span></div>';

    echo $output;
}

add_action('woocommerce_email_customer_details','add_floor_number_checkout_field_to_emails_notifications', 20, 4 );
function add_floor_number_checkout_field_to_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {

    $output = '';
    $shipping_floor_number = get_post_meta( $order->id, '_shipping_floor_number', true );

    if ( !empty($shipping_floor_number) )
        $output .= '<div><strong>' . __('Floor Number:', 'custom-domain') . '</strong> <span class="text">' . $shipping_floor_number . '</span></div>';

    echo $output;
}

This is working great but when I create a manual order from the backend the values do not get pull from the user data they are always empty.
what am I missing?

1 Answers

There are some mistakes in your code: Now the user data can be correctly displayed and changed on Admin User pages.

There is also some missing code to be able to Ajax load the additional custom addresses fields when creating a manual new order.

I have also sorted (reordered) the custom fields in the right location on admin order editable addresses and on admin User dashboard too.

so I have revisited completely your code. The first function handle your custom field settings that are loaded on all other functions.

The code:

// Custom function that handle the Custom field settings
function custom_checkout_fields_settings() {
    $text_domain = 'custom-domain';

    return array(
        'house_number' => __('House number', $text_domain),
        'floor_number' => __('Floor number', $text_domain),
    );
}

// Add custom billing fields to Checkout and My account edit addresses
add_filter( 'woocommerce_billing_fields' , 'custom_billing_fields' );
function custom_billing_fields( $fields ) {
    $settings = custom_checkout_fields_settings(); // Load settings

    // Loop through setting fields
    foreach ( $settings as $field_key => $field_label ) {
        $fields['billing_'.$field_key] = array(
            'type'        => 'text',
            'placeholder' => $field_label,
            'class'       => $field_key === 'house_number' ? array('form-row-first') : array('form-row-last'),
            'required'    => false,
            'clear'       => true,
            'priority'    => $field_key === 'house_number' ? 61 : 62,
        );
    }
    return $fields;
}

// Add custom shipping fields to Checkout and My account edit addresses
add_filter( 'woocommerce_shipping_fields' , 'custom_shipping_fields' );
function custom_shipping_fields( $fields ) {
    $settings = custom_checkout_fields_settings(); // Load settings

    // Loop through setting fields
    foreach ( $settings as $field_key => $field_label ) {
        $fields['shipping_'.$field_key] = array(
            'type'        => 'text',
            'placeholder' => $field_label,
            'class'       => $field_key === 'house_number' ? array('form-row-first') : array('form-row-last'),
            'required'    => false,
            'clear'       => true,
            'priority'    => $field_key === 'house_number' ? 61 : 62,
        );
    }
    return $fields;
}

// Display editable custom fields on admin single order pages
add_filter( 'woocommerce_admin_billing_fields' , 'admin_single_order_custom_addresses_fields' );
add_filter( 'woocommerce_admin_shipping_fields' , 'admin_single_order_custom_addresses_fields' );
function admin_single_order_custom_addresses_fields( $fields ) {
    $settings = custom_checkout_fields_settings(); // Load settings
    $fields_2 = array(); // Initializing

    // Reorder admin editable fields (Loop through setting fields)
    foreach( $fields as $key => $field_data ) {
        $fields_2[$key] = $field_data;

        // Insert new fields after 'address_2'
        if( 'address_2' === $key )
        {
            // Loop through setting fields
            foreach ( $settings as $field_key => $field_label ) {
                $fields_2[$field_key] = array(
                    'label'         => $field_label,
                    'show'          => '0',
                    'wrapper_class' => $field_key === 'floor_number' ? '_billing_phone_field' : '',
                );
            }
        }
    }
    return $fields_2; // return sorted fields
}

// Load Ajax custom field data as customer billing/shipping address fields
add_filter( 'woocommerce_ajax_get_customer_details' , 'add_custom_fields_to_ajax_customer_details', 10, 3 );
function add_custom_fields_to_ajax_customer_details( $data, $customer, $user_id ) {
    $settings = custom_checkout_fields_settings(); // Load settings

    // Loop through setting fields
    foreach( $settings as $field_key => $field_label ) {
        $data['billing'][$field_key] = $customer->get_meta('billing_'.$field_key);
        $data['shipping'][$field_key] = $customer->get_meta('shipping_'.$field_key);
    }

    return $data;
}

// Display reordered editable custom fields on admin single User pages
add_filter( 'woocommerce_customer_meta_fields', 'admin_user_custom_field' );
function admin_user_custom_field( $fields ) {
    $settings = custom_checkout_fields_settings(); // Load settings
    $fields_2 = array(); // Initializing

    // Reorder admin editable fields (loop theough exiting fields)
    foreach( $fields as $fieldset_key => $fieldset_data ) {
        foreach( $fieldset_data as $fieldset_data_key => $data ) {
            if( $fieldset_data_key === 'title' ) {
                $fields_2[$fieldset_key][$fieldset_data_key] = $data;
            } else {
                foreach ( $data as $key => $field ) {
                    $fields_2[$fieldset_key][$fieldset_data_key][$key] = $field;

                    // Insert new fields after "address_2"
                    if( $fieldset_key . '_address_2' === $key )
                    {
                        // Loop through setting fields
                        foreach ( $settings as $field_key => $field_label ) {
                            $fields_2[$fieldset_key][$fieldset_data_key][$fieldset_key.'_'.$field_key] = array(
                                'label'         => $field_label,
                                'description' => '',
                            );
                        }
                    }
                }
            }
        }
    }
    return $fields_2;
}

// Display shipping custom fields values on email notifications
add_action('woocommerce_email_customer_details','display_custom_fields_on_emails_notifications', 30, 4 );
function display_custom_fields_on_emails_notifications( $order, $sent_to_admin, $plain_text, $email ) {
    $settings = custom_checkout_fields_settings(); // Load settings

    // Loop through setting fields
    foreach ( $settings as $field_key => $field_label ) {
        $meta_value = $order->get_meta('_shipping_'.$field_key);
        if ( ! empty($meta_value) ) {
            echo '<div><strong>' . $field_label . ':' . '</strong> <span class="text">' . $meta_value . '</span></div>';
        }
    }
}

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

Now your custom fields values are loaded on manual admin New order, when you set a customer or even when you load customer data on existing admin orders (edit).

Related