woocommerce Adding custom field under shipping table (my account-order view/ thank you) - php

With the help of these 2 posts (WooCommerce editable custom checkout field and displayed in formatted address)( Add additional fields to Admin User under Customer shipping section in Woocommerce), I added the custom field in the checkout, my account, single order, admin, and email. but there are 3 more area I would like to show this custom field and I couldn't find the hook needed to show them. I searched online but with no luck at all. I would love it if someone could guide me on this.
1- under shipping address table in thank you page
2- under shipping address table in order view on my account page
3- I would like to show the field in the address on my account. but its only visible when I click edit
this is the code I used to add the extra field and its working so far
// HOUSE NUMBER EXTRA FIELD
// display shipping House Number in checkout and my account edit shipping address
add_filter( 'woocommerce_shipping_fields', 'add_shipping_house_number_field' );
function add_shipping_house_number_field( $fields ) {
$fields['shipping_house_number'] = array(
'label' => __( 'House Number', 'woocommerce' ),
//'required' => true,
'class' => array( 'form-row-first' ),
'priority' => 61,
);
return $fields;
}
// Display editable custom fields on admin single order pages (backend new order) edit pages inside edit shipping section
add_filter( 'woocommerce_admin_shipping_fields' , 'add_order_admin_edit_shipping_house_number' );
function add_order_admin_edit_shipping_house_number( $fields ) {
// Include shipping house_number as editable field
$fields['house_number'] = array( 'label' => __( 'House Number', 'woocommerce' ), 'show' => '0' );
return $fields;
}
// Load Ajax custom field data as customer billing/shipping address fields in backend new order (data will be pulled from the database)
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 ) {
$data['shipping'][house_number] = $customer->get_meta('shipping_house_number');
return $data;
}
// Display reordered editable custom fields on admin single User pages
add_filter( 'woocommerce_customer_meta_fields', 'house_number_customer_meta_fields', 10, 1 );
function house_number_customer_meta_fields( $fields ) {
$fields['shipping']['fields']['shipping_house_number'] = array(
'label' => __( 'House Number', 'woocommerce' ),
);
return $fields;
}
// Adding custom placeholder to woocommerce formatted address only on Backend
add_filter( 'woocommerce_localisation_address_formats', 'admin_localisation_address_formats', 50, 1 );
function admin_localisation_address_formats( $address_formats ){
// Only in backend (Admin)
if( is_admin() || ! is_wc_endpoint_url() ) {
foreach( $address_formats as $country_code => $address_format ) {
$address_formats[$country_code] .= "\n{house_number}";
}
}
return $address_formats;
}
// Custom placeholder replacement to woocommerce formatted address
add_filter( 'woocommerce_formatted_address_replacements', 'custom_formatted_address_replacements', 10, 2 );
function custom_formatted_address_replacements( $replacements, $args ) {
$replacements['{house_number}'] = ! empty($args['house_number']) ? $args['house_number'] : '';
return $replacements;
}
// Add the shipping house number value to be displayed on email notifications under shipping address
add_filter( 'woocommerce_order_formatted_shipping_address', 'add_shipping_house_number_to_formatted_shipping_address', 100, 2 );
function add_shipping_house_number_to_formatted_shipping_address( $shipping_address, $order ) {
global $pagenow, $post_type;
// Not on admin order edit pages (as it's already displayed).
if( ! ( $pagenow === 'post.php' && $post_type === 'shop_order' && isset($_GET['action']) && $_GET['action'] === 'edit' ) ) {
// Include shipping phone on formatted shipping address
$shipping_address['house_number'] = $order->get_meta('_shipping_house_number');
}
return $shipping_address;
}

For thank you page and my account view order you can use WC woocommerce_order_get_formatted_shipping_address filter hook.
function add_woocommerce_order_get_formatted_shipping_address( $address, $empty_content, $raw_address, $order ){
$address .= '<br/> this is custom text';
return $address;
}
add_filter( 'woocommerce_order_get_formatted_shipping_address', 'add_woocommerce_order_get_formatted_shipping_address', 10, 4 );
Thank you Page
My Account View Order.
My Account edit address
You need to override. woocommerce\templates\myaccount\my-address.php
to your theme or plugin.

Related

WooCommerce custom create account checkbox on checkout

We just moved and merged the WooCommerce account password field on the checkout page from the "Account" group to the "Billing" field group. This works nicely. Also, we create a new checkbox field and add this to the billing section. Without that, the "Create an account" checkbox will still be at the default position. To do so, we created a new checkbox with jQuery.
Thanks to the following articles:
How to move the create account checkbox on Woocommerce checkout page
Reordering checkout fields in WooCommerce 3
With our current code, the moved password field is always visible. We want to have it the same way as WooCommerce default works. This means the password field should only be visible when the checkbox is active. WooCommerce by default has an excellent hide & Show CSS in place. However, I'm not able to use the identical CSS (or maybe script?!).
How can we connect the custom checkbox with the account password field?
// Move Account password field into billing section
function move_password_field($checkout_fields){
// Move Account Password into Billing
$checkout_fields['billing']['account_password'] = $checkout_fields['account']['account_password'];
// Remove Password from Billing
unset($checkout_fields['account']['account_password']);
return $checkout_fields;
}
add_filter('woocommerce_checkout_fields', 'move_password_field', 999);
// CSS rules
add_action( 'woocommerce_before_checkout_billing_form', 'move_checkout_create_an_account_css' );
function move_checkout_create_an_account_css() {
if( ! is_user_logged_in() ) :
?><style>
.woocommerce-account-fields label.woocommerce-form__label-for-checkbox {display: none !important;}
#account_cb_field {margin-top: 32px;}
#account_cb_field input {margin-right: 6px;}
</style>
<?php
endif;
}
// Add a checkbox to billing section
add_filter( 'woocommerce_checkout_fields', 'move_checkout_create_an_account_checkbox' );
function move_checkout_create_an_account_checkbox( $fields ) {
if( ! is_user_logged_in() ) {
// Make email field on half on left side
$fields['billing']['billing_email']['class'] = array('form-row-wide');
// Custom checkbox on half right side
$fields['billing']['account_cb'] = array(
'type' => 'checkbox',
'label' => __("Create an account?", "woocommerce"),
'class' => array('form-row-wide'),
);
}
return $fields;
}
// remove "(optional)" from the new checkbox
add_filter( 'woocommerce_form_field' , 'remove_checkout_optional_fields_label', 10, 4 );
function remove_checkout_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() && $key === 'account_cb' ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// The jQuery code
add_action( 'wp_footer', 'move_checkout_create_an_account_js' );
function move_checkout_create_an_account_js() {
if ( ! is_user_logged_in() && is_checkout() && ! is_wc_endpoint_url() ) :
?><script>
(function($){
$('input[name=account_cb]').on( 'click', function() {
$('input[name=createaccount]').trigger('click');
});
})(jQuery);
</script>
<?php
endif;
}

Add WooCommerce VAT Number Checkout Page [duplicate]

This question already has an answer here:
Custom VAT field issue in Woocommerce
(1 answer)
Closed 10 months ago.
I added a function to the website according to the instructions. Unfortunately, I have an error in "received order" and in the admin panel "customer order"
/***************************** FRONTEND ****************************************/
/**************************
Filter to add a VAT field to:
- My Account - Edit Form -- Billing fields
- Checkout - Edit Form - Billing Fields
This function is also reordering the form fields.
***************************/
function add_woocommerce_billing_fields($billing_fields){
//reorder woo my billing address form fields
$billing_fields2['billing_first_name'] = $billing_fields['billing_first_name'];
$billing_fields2['billing_last_name'] = $billing_fields['billing_last_name'];
$billing_fields2['billing_vat'] = array(
'type' => 'text',
'label' => __('VAT number', 'keyelp-shop-customization' ),
'class' => array('form-row-wide'),
'required' => false,
'clear' => true
);
$merged_billing_fields = $billing_fields2 + $billing_fields;
return $merged_billing_fields;
}
add_filter('woocommerce_billing_fields' , 'add_woocommerce_billing_fields');
/*********
Filters to add VAT when printing billing address on:
- (1) My account
- (2) Checkout - Order Received (after checkout completion),
+++ Additional filters to format the printed output.
********/
// (1) Printing the Billing Address on My Account
add_filter( 'woocommerce_my_account_my_address_formatted_address', 'njengah_my_account_my_address_formatted_address', 10, 3 );
function njengah_my_account_my_address_formatted_address( $fields, $customer_id, $type ) {
if ( $type == 'billing' ) {
$fields['vat'] = get_user_meta( $customer_id, 'billing_vat', true );
}
return $fields;
}
// (2) Checkout -- Order Received (printed after having completed checkout)
add_filter( 'woocommerce_order_formatted_billing_address', 'njengah_add_vat_formatted_billing_address', 10, 2 );
function njengah_add_vat_formatted_billing_address( $fields, $order ) {
$fields['vat'] = $order->billing_vat;
return $fields;
}
// Creating merger VAT variables for printing formatting
add_filter( 'woocommerce_formatted_address_replacements', 'njengah_formatted_address_replacements', 10, 2 );
function njengah_formatted_address_replacements( $address, $args ) {
$address['{vat}'] = '';
$address['{vat_upper}']= '';
if ( ! empty( $args['vat'] ) ) {
$address['{vat}'] = $args['vat'];
$address['{vat_upper}'] = strtoupper($args['vat']);
}
return $address;
}
//Defining the Spanish formatting to print the address, including VAT.
add_filter( 'woocommerce_localisation_address_formats', 'njengah_localisation_address_format' );
function njengah_localisation_address_format( $formats ) {
$formats['ES'] = "{name}\n{company}\n{vat_upper}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}";
return $formats;
}
/***************************** ADMIN USER PROFILE PAGE ****************************************/
/***************
Filter to add VAT Customer meta fields (user profile field on the billing address grouping)
*****************/
add_filter( 'woocommerce_customer_meta_fields', 'njengah_customer_meta_fields' );
function njengah_customer_meta_fields( $fields ) {
$fields['billing']['fields']['billing_vat'] = array(
'label' => __( 'VAT number', 'njengah' )
);
return $fields;
}
/*************************** ADMIN ORDER PAGE ****************************************/
/*********
Filter to add VAT to the Edit Form on Order -- Admin page
*********/
add_filter( 'woocommerce_admin_billing_fields', 'njengah_admin_billing_fields' );
function njengah_admin_billing_fields( $fields ) {
$fields['vat'] = array(
'label' => __( 'VAT number', 'njengah' ),
'show' => true
);
return $fields;
}
/****************
Filter to copy the VAT field from User meta fields to the Order Admin form (after clicking the dedicated button on the admin page)
******************/
add_filter( 'woocommerce_found_customer_details', 'njengah_found_customer_details' );
function njengah_found_customer_details( $customer_data ) {
$customer_data['billing_vat'] = get_user_meta( $_POST['user_id'], 'billing_vat', true );
return $customer_data;
}
The error that appears is
Order properties should not be accessed directly. Backtrace:
require('wp-admin/edit-form-advanced.php'), do_meta_boxes,
WC_Meta_Box_Order_Data::output,
WC_Order->get_formatted_billing_address,
apply_filters('woocommerce_order_formatted_billing_address'),
WP_Hook->apply_filters, add_vat_formatted_billing_address,
WC_Abstract_Legacy_Order->__get, wc_doing_it_wrong
what could be the problem?
The error says Order properties should not be accessed directly.
You have called the order vat metadata like this $order->billing_vat;. Instead you can get the metadata like $order->get_meta('billing_vat'); or by using the function get_post_meta($order->get_id(), 'billing_vat', true);
Update the function like this.
// (2) Checkout -- Order Received (printed after having completed checkout)
add_filter( 'woocommerce_order_formatted_billing_address', 'njengah_add_vat_formatted_billing_address', 10, 2 );
function njengah_add_vat_formatted_billing_address( $fields, $order ) {
$fields['vat'] = get_post_meta($order->get_id(), 'billing_vat', true);
return $fields;
}

Add a field to coupon settings and display the value on Woocommerce admin order list

I am having some really hard times trying to make it work.
I've had an idea in back of my head to:
be able to assign single user to a coupon code through an extra field in general coupon tab, which is listing unassigned users to coupon codes
I dont want to use third party extensions, custom-fields, etc. I was hoping I'll be able to do it through meta data but I failed. Not sure how to get it done properly.
add two extra columns on orders page and display both coupon code and user assigned to it.
After some time reading docs and xDebugging in phpstorm I have also failed to get it done.
function order_sellers_and_coupons_columns_values($column)
{
global $post, $the_order;
if ($column == 'order_coupon_code') {
$coupons = $the_order->get_used_coupons(); // not sure how to get coupon object by the coupon code
echo (count($coupons)) ? $coupons[0] : '';
}
}
// even though I see the order objects have an items and coupon lines property,
// which is an object, i can't get access to it
$the_order->items["coupon_lines"]
I am not asking for ready-to-go solution, but to show me the way how to get it done.
Thanks in advance for any kind of help.
In WooCommerce admin single coupon pages, we add an extra field for the seller (dealer):
// Add a custom field to Admin coupon settings pages
add_action( 'woocommerce_coupon_options', 'add_coupon_text_field', 10 );
function add_coupon_text_field() {
woocommerce_wp_text_input( array(
'id' => 'seller_id',
'label' => __( 'Assing a seller (dealer)', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Assign a seller / dealer to a coupon', 'woocommerce' ),
'desc_tip' => true,
) );
}
// Save the custom field value from Admin coupon settings pages
add_action( 'woocommerce_coupon_options_save', 'save_coupon_text_field', 10, 2 );
function save_coupon_text_field( $post_id, $coupon ) {
if( isset( $_POST['seller_id'] ) ) {
$coupon->update_meta_data( 'seller_id', sanitize_text_field( $_POST['seller_id'] ) );
$coupon->save();
}
}
Then using the following you will add to admin orders list the coupon code (when it's used in the order) with the seller / dealer name:
// Adding a new column to admin orders list
add_filter( 'manage_edit-shop_order_columns', 'custom_shop_order_column' );
function custom_shop_order_column($columns)
{
$reordered_columns = array();
// Inserting columns to a specific location
foreach( $columns as $key => $column){
$reordered_columns[$key] = $column;
if( $key == 'order_status' ){
// Inserting after "Status" column
$reordered_columns['coupons'] = __( 'Coupon','theme_domain');
}
}
return $reordered_columns;
}
// Adding used coupon codes
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 10, 2 );
function custom_orders_list_column_content( $column, $post_id )
{
global $the_order;
if ( $column == 'coupons' ) {
$coupons = (array) $the_order->get_used_coupons();
$dealers = [];
foreach( $coupons as $coupon_code ) {
$coupon = new WC_Coupon( $coupon_code );
$dealers[] = $coupon->get_meta('seller_id');
}
if( count($coupons) > 0 )
echo implode( ', ', $coupons );
if( count($dealers) > 0 )
echo '<br><small>(' . implode( ', ', $dealers ) . ')</small>';
}
}
All code goes in functions.php file of your active child theme (or active theme). Tested and works.
On Admin coupon single pages:
On Admin edit orders list:

Disabling Add to Cart Button for Specific WooCommerce Products

I'm trying to disable adding to cart certain products which have the "Call to Order" checkbox ticked (see code below) on the product editor.
add_action( 'woocommerce_product_options_general_product_data', 'custom_general_product_data_custom_fields' );
/**
* Add `Call to Order` field in the Product data's General tab.
*/
function custom_general_product_data_custom_fields() {
// Checkbox.
woocommerce_wp_checkbox(
array(
'id' => '_not_ready_to_sell',
'wrapper_class' => 'show_if_simple',
'label' => __( 'Call to Order', 'woocommerce' ),
'description' => __( '', 'woocommerce' )
)
);
}
add_action( 'woocommerce_process_product_meta', 'custom_save_general_proddata_custom_fields' );
/**
* Save the data values from the custom fields.
* #param int $post_id ID of the current product.
*/
function custom_save_general_proddata_custom_fields( $post_id ) {
// Checkbox.
$woocommerce_checkbox = isset( $_POST['_not_ready_to_sell'] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_not_ready_to_sell', $woocommerce_checkbox );
}
add_filter( 'woocommerce_is_purchasable', 'custom_woocommerce_set_purchasable', 10, 2);
/**
* Mark "Not ready to sell" products as not purchasable.
*/
function custom_woocommerce_set_purchasable() {
$not_ready_to_sell = get_post_meta( get_the_ID(), '_not_ready_to_sell' , true);
return ( 'yes' == $not_ready_to_sell ? false : true );
}
add_filter( 'woocommerce_product_add_to_cart_text', 'custom_product_add_to_cart_text' );
/**
* Change "Read More" button text for non-purchasable products.
*/
function custom_product_add_to_cart_text() {
$not_ready_to_sell = get_post_meta( get_the_ID(), '_not_ready_to_sell', true );
if ( 'yes' === $not_ready_to_sell ) {
return __( 'Call to Order', 'woocommerce' );
} else {
return __( 'Add to Cart', 'woocommerce' );
}
}
The products that have the checkbox ticked, are in fact not purchasable, which is the desired outcome.
The problem I'm having is when I click "Add to Cart" for purchasable products (those without the checkbox ticked) on the product catalog page, I am redirected to the product page and a default WooCommerce message "Sorry, this product cannot be purchased." appears. What should be happening is that when the "Add to Cart" button is clicked, the product is automatically added to the cart.
Also from the single product page, I can add the purchasable cart without a problem.
I am not sure why this is happening this way. Any ideas?
I have tested your code and it work without problems… I don't have the problematic behavior you describe… So something else is making trouble:
You will need first to make a database backup… Then you should try to:
Check if in your other customizations, there is something that is disabling Ajax add to cart and making that message appear. Try to comment your other customizations to find the guilty one.
Try to disable all third party plugins related to Woocommerce (except Woocommerce). If the problem is gone, re-enable them one by one to find the guilty.
The problem could come from the theme too.
Now since Woocommerce 3 and introduced CRUD Objects, your code is a bit outdated.
Here is revisited and enhanced code version (for Woocommerce 3+):
// Add a custom field in the Product data's General tab (for simple products).
add_action( 'woocommerce_product_options_general_product_data', 'add_general_product_data_custom_field' );
function add_general_product_data_custom_field() {
woocommerce_wp_checkbox( array( // Checkbox.
'id' => '_not_ready_to_sell',
'label' => __( 'Call to Order', 'woocommerce' ),
'wrapper_class' => 'show_if_simple',
) );
}
// Save custom field value
add_action( 'woocommerce_admin_process_product_object', 'save_general_product_data_custom_field', 10, 1 );
function save_general_product_data_custom_field( $product ) {
$product->update_meta_data( '_not_ready_to_sell', isset( $_POST['_not_ready_to_sell'] ) ? 'yes' : 'no' );
}
// Make not purchasable, products with '_not_ready_to_sell' meta data set to "yes" (for simple products)
add_filter( 'woocommerce_is_purchasable', 'filter_woocommerce_set_purchasable', 10, 2);
function filter_woocommerce_set_purchasable( $purchasable, $product ) {
return 'yes' === $product->get_meta( '_not_ready_to_sell' ) && $product->is_type('simple') ? false : $purchasable;
}
// Change button text to "Call to Order" for simple products not purchasable.
add_filter( 'woocommerce_product_add_to_cart_text', 'filter_product_add_to_cart_text', 10, 2 );
function filter_product_add_to_cart_text( $button_text, $product ) {
if ( 'yes' === $product->get_meta( '_not_ready_to_sell' ) && $product->is_type('simple') ) {
$button_text = __( 'Call to Order', 'woocommerce' );
}
return $button_text;
}
Code goes on function.php file of your active child theme (or active theme). It could works.

For Returning Customer Hide or Get Email for added "Repeat Email Address" on WooCommerce Checkout Page

I've added a Repeat Email Address field on the WooCommerce checkout page with the following add function:
// EMAIL Confirmation on CHECKOUT PAGE
add_filter( 'woocommerce_checkout_fields' , 'email_verification_field_checkout' );
function email_verification_field_checkout( $fields ) {
$fields['billing']['billing_email']['class'] = array('form-row-first');
$fields['billing']['billing_email_verification'] = array(
'label' => __('Repeat Email Adress', 'woocommerce'),
'required' => true,
'class' => array('form-row-last'),
'clear' => true,
'priority' => 999,
);
return $fields;
}
// CHECK IF THE TWO EMAILS MATCH !!!
add_action('woocommerce_checkout_process', 'mycheck_email_addresses');
function mycheck_email_addresses() {
$email1 = $_POST['billing_email'];
$email2 = $_POST['billing_email_verification'];
if ( $email2 !== $email1 ) {
wc_add_notice( __( 'Your email addresses don't match!', 'woocommerce' ), 'error' );
}
}
Returning Customers can login on top of the page.
WooCommerce then gets the email address for the filed "billing_email" adress.
1) Is there a way to add a function to do the same for the added "billing_email_verification" field?
2) I tried an add function for the case that a Returning Customer logs in on top of the checkout page: In this case I would love to hide the "Repeat Email Address" field for better customer experience. But unfortunately that didn't work. I'm just starting out to understand filters and hooks and would appreciate a helping hand :)
add_filter( 'woocommerce_checkout_fields' , 'my_override_checkout_fields' );
function my_override_checkout_fields( $fields ) {
if( is_user_logged_in() ){
unset($fields['billing']);
$fields['billing_email_verification'] = array();
}
return $fields;
}
I've found the mistake in the solution for case 2)
Here is the correct filter for case 2)
add_filter( 'woocommerce_checkout_fields' , 'my_override_checkout_fields' );
function my_override_checkout_fields( $fields ) {
if( is_user_logged_in() ){
unset($fields['billing']['billing_email_verification']);
}
return $fields;
}
Anyhow, I would love to learn how I can approach case 1) something with get_value
Does someone know how to do this?

Categories