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;
}
Related
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.
Hi every one let me try to explain this.
PLEASE NOTE: i use the woo commerce block plugin (for the cart and checkout pages to replace the original shortcode)
i want to change my instances where the word shipping is to change to the word Delivery
i use this hook in my functions.php and it did change the one word to delivery so that worked
add_filter('woocommerce_shipping_package_name', 'change_shipping_text_to_delivery', 20, 3 );
function change_shipping_text_to_delivery( $sprintf, $i, $package ) {
$sprintf = sprintf( _nx( 'Delivery', 'Delivery %d', ( $i + 1 ), 'delivery packages', 'woocommerce' ), ( $i + 1 ) );
return $sprintf;
}
as you can see on the cart page it only changed the one word not the other two
okay then when i go to my PROCEED TO CHECKOUT AND GO TO THE PAGE
THIS IS MY CHECKOUT PAGE(also UNCHAGED)
i have insert this in my php functions did not work
/*
* Change the string "Shipping" to "Delivery" on Order Received page.
*/
add_filter('gettext', 'translate_reply');
add_filter('ngettext', 'translate_reply');
function translate_reply($translated) {
$translated = str_ireplace('Shipping', 'Delivery', $translated);
return $translated;
}
i also tried going to my plugin folder
i did get some code in there where i replaced the strings shipping to delviery and it did not do anything !
return (
<FormStep
id="shipping-fields"
disabled={ checkoutIsProcessing }
className="wc-block-checkout__shipping-fields"
title={ __( 'Shipping address', 'woo-gutenberg-products-block' ) }
description={ __(
'Enter the physical address where you want us to deliver your order.',
'woo-gutenberg-products-block'
) }
>
{ children }
<CheckboxControl
className="wc-block-checkout__use-address-for-billing"
label={ __(
'Use same address for billing',
'woo-gutenberg-products-block'
) }
checked={ shippingAsBilling }
onChange={ ( isChecked ) => setShippingAsBilling( isChecked ) }
/>
</FormStep>
Please can someone help me i just want to change those words to DELIVERY
Try something like below. This uses a filter hook to change the values in the $fields array. In your case, you are changing order details
add_filter( 'woocommerce_checkout_fields' , 'your_function' );
function your_function ( $fields ) {
$fields['shipping']['shipping_address']['label'] = "Delivery Address";
return $fields;
}
This would go in your functions.php file.
i did come right with this code but i had to remove the woo commerce gutenberg block i reverted back to the default woo commerce shortcodes
add_filter('woocommerce_shipping_package_name', 'change_shipping_text_to_delivery', 20, 3 );
function change_shipping_text_to_delivery( $sprintf, $i, $package ) {
$sprintf = sprintf( _nx( 'Delivery', 'Delivery %d', ( $i + 1 ), 'delivery packages', 'woocommerce' ), ( $i + 1 ) );
return $sprintf;
}function shipchange( $translated_text, $text, $domain ) {
switch ( $translated_text ) {
case 'Ship to a different address?' :
$translated_text = __( 'Deliver to a different address?', 'woocommerce' );
break;
}
return $translated_text;
}
add_filter('gettext', 'shipchange', 20, 3);
add_filter( 'woocommerce_shipping_package_name' , 'woocommerce_replace_text_shipping_to_delivery', 10, 3);
/**
*
* Function to replace shipping text to delivery text
*
* #param $package_name
* #param $i
* #param $package
*
* #return string
*/
function woocommerce_replace_text_shipping_to_delivery($package_name, $i, $package){
return sprintf( _nx( 'Delivery', 'Delivery %d', ( $i + 1 ), 'shipping packages', 'put-here-you-domain-i18n' ), ( $i + 1 ) );
}
/*
* Change the string "Shipping" to "Delivery" on Order Received page.
*/
add_filter('gettext', 'translate_reply');
add_filter('ngettext', 'translate_reply');
function translate_reply($translated) {
$translated = str_ireplace('Shipping', 'Delivery', $translated);
return $translated;
}
in Wordpress admin dashboard, when you open woocommerce order page, you will see list of the orders and the columns are (Order, Date, Status, Billing, Shipping, Total, Actions)
I would like to add a new button for Action list and then add this action to send the Email Invoice to the customers which orders are still on-hold.
I have created the column and the button as below, but I have trouble with calling the action button to send the invoice to the customers for each order.
please advice.
add_filter( 'woocommerce_admin_order_actions', 'add_custom_order_status_actions_button', 100, 2 );
function add_custom_order_status_actions_button( $actions, $order ) {
if ( $order->has_status( array( 'on-hold' ) ) ) {
// The key slug defined for your action button
$action_slug = 'invoice';
$status = $_GET['status'];
$order_id = method_exists($the_order, 'get_id') ? $the_order->get_id() : $the_order->id;
// Set the action button
$actions[$action_slug] = array(
'url' => admin_url('post.php?post=' . $post_id . '&action=edit&message=11'),
'name' => __( 'Invoice', 'woocommerce' ),
'action' => $action_slug,
);
}
return $actions;
}
add_action( 'admin_head', 'add_custom_order_status_actions_button_css' );
function add_custom_order_status_actions_button_css() {
$action_slug = "invoice"; // The key slug defined for your action button
echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "\e029" !important; }</style>';
}
Updated (added missing ').
The following will add on admin orders list actions column an action button for orders with an "on hold" status. The button send the customer invoice notification via admin Ajax.
The complete code:
add_filter( 'woocommerce_admin_order_actions', 'add_admin_order_custom_actions_button', 100, 2 );
function add_admin_order_custom_actions_button( $actions, $order ) {
if ( $order->has_status( array( 'on-hold' ) ) ) {
// The key slug defined for your action button
$action_slug = 'email_invoice';
// Set the action button
$actions[$action_slug] = array(
'url' => wp_nonce_url(
admin_url('admin-ajax.php?action=send_invoice_email&order_id=' . $order->get_id() ),
'send-invoice-email'
),
'name' => __( 'Send Invoice', 'woocommerce' ),
'action' => $action_slug,
);
}
return $actions;
}
add_action( 'wp_ajax_send_invoice_email', 'trigger_customer_email_invoice' );
function trigger_customer_email_invoice() {
if ( current_user_can('edit_shop_orders') && check_admin_referer('send-invoice-email') &&
isset($_GET['order_id']) && get_post_type( absint( wp_unslash($_GET['order_id']) ) ) === 'shop_order' ) {
$order_id = absint( wp_unslash($_GET['order_id']) );
WC()->mailer()->get_emails()['WC_Email_Customer_Invoice']->trigger($order_id); // Send email
update_post_meta( $order_id, '_invoice_sent', 'OK' ); // For testing purpose (to be removed)
}
}
add_action( 'admin_head', 'add_custom_order_status_actions_button_css' );
function add_custom_order_status_actions_button_css() {
$action_slug = "email_invoice"; // The key slug defined for your action button
echo '<style>.wc-action-button-'.$action_slug.'::after { font-family: woocommerce !important; content: "\e02d" !important; }</style>';
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
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:
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?