4

I am not a developer but somehow managed to add Woocommerce custom fields to checkout and order edit pages. There are similar questions, but I can't find the correct solution.

The custom fields are visible in the admin order edit page but they don't display the values and are not added to order emails.

What am I missing?

Please see screenshot at the end.

Here is all the code a put together:

// Woocommerce - Add user custom billing fields
// =============================================================================

function add_woocommerce_admin_billing_fields($billing_fields) {
    $billing_fields['billing_birthday'] = array(
        'label' => __('Datum rojstva', 'woocommerce')
    );
    $billing_fields['billing_socialno'] = array(
        'label' => __('Davčna številka', 'woocommerce')
    );

    return $billing_fields;
}
add_filter('woocommerce_admin_billing_fields', 'add_woocommerce_admin_billing_fields');

function add_woocommerce_found_customer_details($customer_data, $user_id, $type_to_load) {
    if ($type_to_load == 'billing') {
        $customer_data[$type_to_load . 'billing_birthday'] = get_user_meta($user_id, $type_to_load . 'billing_birthday', true);
        $customer_data[$type_to_load . 'billing_socialno'] = get_user_meta($user_id, $type_to_load . 'billing_socialno', true);

    }
    return $customer_data;
}
add_filter('woocommerce_found_customer_details', 'add_woocommerce_found_customer_details', 10, 3);

function add_woocommerce_billing_fields($billing_fields) {
    $billing_fields['billing_birthday'] = array(
        'type' => 'tel',
        'label' => __('Datum rojstva'),
        'value' => get_post_meta( $order->id, 'billing_birthday', true ),
        'placeholder' => __('dd/mm/yyyy', 'placeholder'),
        'pattern' => __('\d{1,2}/\d{1,2}/\d{4}', 'pattern' ),
        'class' => array('form-row-first'),
        'required' => true,
        'clear' => true

    );
    $billing_fields['billing_socialno'] = array(
        'type' => 'tel',
        'label' => __('Davčna številka'),
        'value' => get_post_meta( $order->id, 'billing_socialno', true ),
        'placeholder' => _x('8-mestna številka', 'placeholder'),
        'class' => array('form-row-last'),
        'required' => false,
        'clear' => true
    );

    return $billing_fields;
}
add_filter('woocommerce_billing_fields', 'add_woocommerce_billing_fields');

//Doda user meta v backend profil
function add_woocommerce_customer_meta_fields($billing_fields) {
    if (isset($billing_fields['billing']['fields'])) {
        $billing_fields['billing']['fields']['billing_birthday'] = array(
            'label' => __('Datum rojstva', 'woocommerce'),
            'description' => 'Pa kaj bo končno ratalo memo milo?'
        );
        $billing_fields['billing']['fields']['billing_socialno'] = array(
            'label' => __('Davčna številka', 'woocommerce'),
            'description' => ''
        );

    }
    return $billing_fields;
}
add_filter('woocommerce_customer_meta_fields', 'add_woocommerce_customer_meta_fields');

function add_woocommerce_order_fields($address, $order) {
    $address['billing_birthday'] = $order->billing_birthday . get_post_meta($order->id, '_billing_birthday', true) ;
    $address['billing_socialno'] = $order->billing_socialno;
    return $address;
}
add_filter('woocommerce_order_formatted_billing_address', 'add_woocommerce_order_fields', 10, 2);

function add_woocommerce_formatted_address_replacements($replace, $args) {
    $replace['{billing_birthday}'] = !empty($args['billing_birthday']) ? 'Datum rojstva' . $args['billing_birthday'] : '';
    $replace['{billing_socialno}'] = !empty($args['billing_socialno']) ? 'Davčna številka' . $args['billing_socialno'] : '';
    return $replace;
}
add_filter('woocommerce_formatted_address_replacements', 'add_woocommerce_formatted_address_replacements', 10, 2);

function add_woocommerce_localisation_address_formats($formats) {
    $formats['default'] = $formats['default'] . "\n{billing_birthday}\n{billing_socialno}";
    return $formats;
}
add_filter('woocommerce_localisation_address_formats', 'add_woocommerce_localisation_address_formats', 10, 1);

// Change field type to tel woocommerce checkout

function bbloomer_change_checkout_field_input_type() {
echo "<script>document.getElementById('billing_postcode').type = 'tel';</script>";
echo "<script>document.getElementById('billing_birthday').type = 'tel';</script>";

}

add_action( 'woocommerce_after_checkout_form', 'bbloomer_change_checkout_field_input_type'); 

screenshot of order edit page

enter image description here

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
Mark Ogner
  • 41
  • 1
  • 6

2 Answers2

5

I have tested your code and there is just some little errors. You are very near to make it work as you expect. so you should need some changes in the following code:

1) Removed the 'values' as this hooked function works for checkout and dont need values (and still less when you are trying to get them from a non existing order).

This will avoid hidden errors and will display the correct values when customer has already filled the fields in a previous purshase…

// Add custom Checkout billing fields
add_filter('woocommerce_billing_fields', 'add_woocommerce_billing_fields', 20, 1);
function add_woocommerce_billing_fields( $billing_fields ) {

    $billing_fields['billing_birthday'] = array(
        'type' => 'tel',
        'label' => __('Datum rojstva'),
        'placeholder' => __('dd/mm/yyyy', 'placeholder'),
        'pattern' => __('\d{1,2}/\d{1,2}/\d{4}', 'pattern' ),
        'class' => array('form-row-first'),
        'required' => true,
        'clear' => true
    );

    $billing_fields['billing_socialno'] = array(
        'type' => 'tel',
        'label' => __('Davčna številka'),
        'placeholder' => _x('8-mestna številka', 'placeholder'),
        'class' => array('form-row-last'),
        'required' => false,
        'clear' => true
    );

    return $billing_fields;
}

// Change field type to tel for woocommerce checkout
add_action( 'woocommerce_after_checkout_form', 'change_checkout_field_input_type');
function change_checkout_field_input_type() {
    echo "<script>document.getElementById('billing_postcode').type = 'tel';</script>";
    echo "<script>document.getElementById('billing_birthday').type = 'tel';</script>";
}

2) The keys where wrong here, so that's why the fields values doesn't get displayed in Admin order edit pages.

It was 'birthday' and 'socialno' instead of 'billing_birthday' and 'billing_socialno'.

// Setting custom fields Keys/Labels pairs in admin edit order pages and allow edit this fields correctly.
add_filter('woocommerce_admin_billing_fields', 'add_woocommerce_admin_billing_fields');
function add_woocommerce_admin_billing_fields($billing_fields) {
    $billing_fields['birthday'] = array( 'label' => __('Datum rojstva', 'woocommerce') );
    $billing_fields['socialno'] = array( 'label' => __('Davčna številka', 'woocommerce') );

    return $billing_fields;
}

3) Get correctly the missing field values to be displayed in Order edit pages.

// Get the field values to be displayed in admin Order edit pages
add_filter('woocommerce_order_formatted_billing_address', 'add_woocommerce_order_fields', 10, 2);
function add_woocommerce_order_fields($address, $order ) {
    $address['billing_birthday'] = get_post_meta( $order->get_id(), '_billing_birthday', true );
    $address['billing_socialno'] = get_post_meta( $order->get_id(), '_billing_socialno', true );
    return $address;
}

4) Other Unchanged hooked functions:

//Doda user meta v backend profil
add_filter('woocommerce_customer_meta_fields', 'add_woocommerce_customer_meta_fields');
function add_woocommerce_customer_meta_fields($fields) {
    if (isset($fields['billing']['fields'])) {
        $fields['billing']['billing_birthday'] = array(
            'label' => __('Datum rojstva', 'woocommerce'),
            'description' => 'Pa kaj bo končno ratalo memo milo?'
        );
        $fields['billing']['billing_socialno'] = array(
            'label' => __('Davčna številka', 'woocommerce'),
            'description' => ''
        );
    }
    return $fields;
}

add_filter( 'woocommerce_found_customer_details', 'add_woocommerce_found_customer_details', 10, 3);
function add_woocommerce_found_customer_details($customer_data, $user_id, $type_to_load) {
    if ($type_to_load == 'billing') {
        $customer_data[$type_to_load . 'billing_birthday'] = get_user_meta($user_id, $type_to_load . 'billing_birthday', true);
        $customer_data[$type_to_load . 'billing_socialno'] = get_user_meta($user_id, $type_to_load . 'billing_socialno', true);

    }
    return $customer_data;
}

//add_filter('woocommerce_formatted_address_replacements', 'add_woocommerce_formatted_address_replacements', 10, 2);
function add_woocommerce_formatted_address_replacements($replace, $args) {
    $replace['{billing_birthday}'] = !empty($args['billing_birthday']) ? 'Datum rojstva' . $args['billing_birthday'] : '';
    $replace['{billing_socialno}'] = !empty($args['billing_socialno']) ? 'Davčna številka' . $args['billing_socialno'] : '';
    return $replace;
}

add_filter('woocommerce_localisation_address_formats', 'add_woocommerce_localisation_address_formats', 10, 1);
function add_woocommerce_localisation_address_formats($formats) {
    $formats['default'] = $formats['default'] . "\n{billing_birthday}\n{billing_socialno}";
    return $formats;
}

Code goes in function.php file of the active child theme (or active theme).


Email notifications - Display the custom fields (with their labels).

Overriding Woocommerce template emails/email-addresses.php via your active child theme:

This template can be overridden by copying from:
plugin/woocommerce/templates/emails/email-addresses.php
To yourtheme/woocommerce/emails/email-addresses.php
Official documentation: Template structure & Overriding templates via a theme

You will insert after line 34 (just after the billing phone) the following:

<?php
    // Billing birthday
    $billing_birthday = get_post_meta($order->get_id(), '_billing_birthday', true );
    echo $billing_birthday ? '<br/>'.__('Datum rojstva', 'woocommerce').': '.$billing_birthday : '';

    // Billing socialno
    $billing_socialno = get_post_meta($order->get_id(), '_billing_socialno', true );
    echo $billing_socialno ? '<br/>'.__('Davčna številka', 'woocommerce').': '.$billing_socialno : '';
?>

Tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • 1
    Thank you for your answer. In the admin order edit page and in the my account page erverything works like a charm! But if i use your snippet the fields in backend profile are not displaying any more...and i would really like to have the option to correct/update cutomers data. So for now i just corrected the keys and left my code as is - with values. – Mark Ogner Jan 26 '18 at 18:45
  • @MarkOgner I don't really catch what do you mean. My answer is just answering your question which is: **Display editable custom fields values in Woocommerce edit order page**. So you could accept this answer, as it was really complicated to find out and it's answering your question. Now what you can do is add an edit at the end of your question, explaining what do you need to have, that is not working with my code (with screenshots if necessary). This way I will edit my answer code too, yo make it work totally… Thanks. – LoicTheAztec Jan 26 '18 at 19:07
  • I really appreciate what you did. Loic. I just wanted to let you know where i am as i didn’t had time to look for the reason of the issue that has come up. Maybe i erased something i shouldn’t along the way. So-thank you and will edit the question as soon as i can. And-please cut me some slack as i am rather new to all of this stackoverflow thing and i learn as i go. – Mark Ogner Jan 27 '18 at 16:55
0

If you want to add your custom field, it is not about just adding new billing details, but anyway it is simple enough.

I recommend you to use hook woocommerce_admin_order_data_after_billing_address, so it will be something like this:

add_action( 'woocommerce_admin_order_data_after_billing_address', 'mishafunction' );        
function mishafunction( $order ){        
    $x = get_post_meta( $order->get_order_number(), 'CUSTOM FIELD NAME', true );
    ?>
    <div class="address">
    <p<?php if( !$x ) echo ' class="none_set"' ?>>
        <strong>Datum rojstva:</strong>
        <?php echo ( $x ) ? $x : '' ?>
    </p>
    </div>
    <div class="edit_address"><?php
    woocommerce_wp_text_input( array(
        'id' => 'CUSTOM FIELD NAME',
        'label' => 'Datum rojstva:',
        'value' => $x,
        'wrapper_class' => 'form-field-wide'
    ) );
    ?></div><?php
}

add_action( 'woocommerce_process_shop_order_meta', 'misha_save_it' );

function misha_save_it( $order_id ){
    update_post_meta( $order_id, 'CUSTOM FIELD NAME', wc_clean( $_POST[ 'CUSTOM FIELD NAME' ] ) );
}

You can also check the complete tutorial here.

Misha Rudrastyh
  • 866
  • 10
  • 16
  • You genious. love your blogs. This code saved my time, thanks :) – Chandan Kumar Thakur Oct 21 '20 at 10:08
  • @misha is it possible to make custom field editable in view orders page. please help here https://wordpress.stackexchange.com/questions/384364/woocommerce-custom-product-fields-need-to-be-editable-after-purchase-in-view-ord – Praveen Mar 03 '21 at 04:44