After Woocommerce update to 3.2, This code below does not work anymore.
add_action( 'woocommerce_email_order_details', 'my_completed_order_email_instructions', 10, 4 );
function my_completed_order_email_instructions( $order, $sent_to_admin, $plain_text, $email ) {
// Only for "Customer Completed Order" email notification
if( 'customer_completed_order' != $email->id ) return;
// Comptibility With WC 3.0+
if ( method_exists( $order, 'get_id' ) ) {
$order_id = $order->get_id();
} else {
$order_id = $order->id;
}
//$order->has_shipping_method('')
$shipping_method_arr = get_post_meta($order_id, '_shipping_method', false); // an array
$rate_id = $shipping_method_arr[0][0]; // the rate ID
if ( 'flat_rate:10' == $rate_id ){
echo pll__("Text 1");
} else {
echo pll__("Text 2");
}
}
What is wrong or obsolete in this code?
What changes need to be done to make it work again?
Here is the correct way to get the Shipping methods used in the Order and make this function works as expected:
add_action( 'woocommerce_email_order_details', 'my_completed_order_email_instructions', 10, 4 );
function my_completed_order_email_instructions( $order, $sent_to_admin, $plain_text, $email ) {
// Only for "Customer Completed Order" email notification
if( 'customer_completed_order' != $email->id ) return;
$found = false; // Initializing variable
// Iterating through Order shipping methods
foreach($order->get_shipping_methods() as $value){
$rate_id = $value->get_method_id(); // Get the shipping rate ID
if ( 'flat_rate:10' == $rate_id )
$found = true;
}
if ($found)
echo '<p>'.__("Text 1 (found)","woocommerce").'</p>';
else
echo '<p>'.__("Text 2 (else)","woocommerce").'</p>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works…
Related
I'm trying to add custom content (2 sentences) after the order table on the WooCommerce
On-Hold
Processing Order
Order Completed
customer emails notifications.
This for all non-USA orders. I tried to get this result by using the woocommerce_email_after_order_table hook.
Here is my initial code but not sure how to make it work.
add_action( 'woocommerce_email_after_order_table', 'NoneUS_custom_content_email', 10, 4 );
function NoneUS_custom_content_email( $order, $sent_to_admin, $plain_text, $email ) {
if( ! ( 'customer_processing_order' == $email->id || 'customer_completed_order' == $email->id ) || 'customer_on_hold_order' == $email->id)) return;
if (strtolower($woocommerce->customer->get_shipping_country()) != 'US') { {
echo '<p><strong>Note:</strong> custom content.</p>';
}
}}
$woocommerce is undefined in your attempt, You can obtain the necessary information via the $order object
So you get:
function action_woocommerce_email_after_order_table( $order, $sent_to_admin, $plain_text, $email ) {
// Target certain email notifications
if ( in_array( $email->id, array( 'customer_on_hold_order', 'customer_processing_order', 'customer_completed_order' ) ) ) {
if ( $order->get_shipping_country() != 'US' ) {
echo '<p><strong>Note:</strong> custom content.</p>';
}
}
}
add_action( 'woocommerce_email_after_order_table', 'action_woocommerce_email_after_order_table', 10, 4 );
I am trying to, based on shipping and if / if not the order note is empty, to add information to the customer complete order email.
Two different messages based on if the order notes field is filled in or not. I've placed test orders but nothing shows up.
This is the code I am trying to get to work:
add_action( 'woocommerce_email_order_details', 'local_pickup_order_instructions', 10, 4 );
function local_pickup_order_instructions( $order, $sent_to_admin, $plain_text, $email ) {
if ( 'customer_completed_order' != $email->id ) return;
foreach( $order->get_items('shipping') as $shipping_item ) {
$shipping_rate_id = $shipping_item->get_method_id();
$method_array = explode(':', $shipping_rate_id );
$shipping_method_id = reset($method_array);
if ('local_pickup' == $shipping_method_id && empty($_POST['order_comments'])){ ?>
<div style="">Your instructions text here</div>
<?php
break;
}
else {
if ('local_pickup' == $shipping_method_id && !empty($_POST['order_comments'] ) ) { ?>
<div style="">Your instructions text here</div>
<?php
}
}
}
}
There are some mistakes in your code… To display a different custom text when shipping method is "Local Pickup" if there is (or not) a customer note, use the following simplified and revisited code:
add_action( 'woocommerce_email_order_details', 'local_pickup_order_instructions', 10, 4 );
function local_pickup_order_instructions( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id === 'customer_completed_order' ) {
$shipping_items = $order->get_items('shipping');
$shipping_item = reset($shipping_items); // Get first shipping item
$customer_note = $order->get_customer_note(); // Get customer note
// Targeting Local pickup shipping methods
if ( strpos( $shipping_item->get_method_id(), 'local_pickup' ) !== false ) {
if ( empty($customer_note) ) {
echo '<div style="color:red;">'.__("Instructions text here… (No customer note)").'</div>'; // Empty order note
} else {
echo '<div style="color:green;">'.__("Instructions text here… (has a customer note)").'</div>'; // Filled order note
}
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
I'm trying to display some "conditional" custom text on the "Order Complete" email, which is sent to the customers when an order is marked as completed. I have used the following code.
Now, I want to make this code conditional, so this code should only be active for the "Gift" Category products. I couldn't find any appropriate Woocommerce functions for this particular functionality.
Any help would be appreciated.
This is what I have for now:
add_action( 'woocommerce_email_before_order_table',
'bbloomer_add_content_specific_email', 20, 4 );
function bbloomer_add_content_specific_email( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id == 'customer_completed_order' ) {
echo '<p class="email-text-conditional">Thank you for your order with Adventure Clues, we have sent your recipient the gift card’</p>';
}
}
Try the following:
add_action( 'woocommerce_email_before_order_table', 'email_before_order_table_conditional_display', 20, 4 );
function email_before_order_table_conditional_display( $order, $sent_to_admin, $plain_text, $email ) {
// Only for "commpeted" order status notification
if ( 'customer_completed_order' !== $email->id ) return;
foreach( $order->get_items() as $item ){
if( has_term( "Gifts", "product_cat", $item->get_product_id() ) ){
echo '<p class="email-text-conditional">Thank you for your order with Adventure Clues, we have sent your recipient the gift card.</p>';
break;
}
if( has_term( "Clothes", "product_cat", $item->get_product_id() ) ){
echo '<p class="email-text-conditional">Thank you for your order with Adventure Clues, we are managing your Clothes.</p>';
break;
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I tried the following code that is displaying a message to all those customers who should receive a customer_processing_order and customer_completed_order when local_pickup is the chosen shipping method.
I noticed I do not store any _shipping_method item within any order meta, but only a thing like: order_item_type: shipping > method_id > local_pickup:3
How can I retrieve it?
I tried this of code without success:
// testo per Ritiro in Sede
add_action( 'woocommerce_email_order_details', 'my_completed_order_email_instructions', 10, 4 );
function my_completed_order_email_instructions( $order, $sent_to_admin, $plain_text, $email ) {
if( 'customer_processing_order' != $email->id ) return;
if ( method_exists( $order, 'get_id' ) ) {
$order_id = $order->get_id();
} else {
$order_id = $order->id;
}
$shipping_method_arr = get_post_meta($order_id, '_shipping_method', false);
$method_id = explode( ':', $shipping_method_arr[0][0] );
$method_id = $method_id[0]; // We get the slug type method
if ( 'local_pickup' == $method_id ){
echo '<p><strong>Ritiro in sede</strong></p>';
}
}
This can be done iterating through order shipping items, this way:
add_action( 'woocommerce_email_order_details', 'my_completed_order_email_instructions', 10, 4 );
function my_completed_order_email_instructions( $order, $sent_to_admin, $plain_text, $email ) {
// Only for processing and completed email notifications to customer
if( ! ( 'customer_processing_order' == $email->id || 'customer_completed_order' == $email->id ) ) return;
foreach( $order->get_items('shipping') as $shipping_item ){
$shipping_rate_id = $shipping_item->get_method_id();
$method_array = explode(':', $shipping_rate_id );
$shipping_method_id = reset($method_array);
// Display a custom text for local pickup shipping method only
if( 'local_pickup' == $shipping_method_id ){
echo '<p><strong>Ritiro in sede</strong></p>';
break;
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.
I have set up a hidden input item using woocommerce_before_add_to_cart_button hook
function add_gift_wrap_field() {
?>`<input type="hidden" id="price_val" name="added_price" value="100.34">`<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
Saving fields against the product:
function save_gift_wrap_fee( $cart_item_data, $product_id ) {
if( isset( $_POST['added_price'] ) ) {
$cart_item_data = array();
$cart_item_data[ "gift_wrap_fee" ] = "YES";
$cart_item_data[ "gift_wrap_price" ] = 100;
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_gift_wrap_fee', 99, 2 );
Now I can echo out the $_POST['added_price'] inside this woocommerce_before_calculate_totals hook.
The code I written is shown below:
function calculate_gift_wrap_fee( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" )) {
/* Gift wrap price */
$additionalPrice = number_format($_POST['added_price'], 2);
$additionalPrice = floatval($additionalPrice);
//echo $additionalPrice; exit(); shows the value
foreach ( $cart_object->cart_contents as $key => $value ) {
if( isset( $value["gift_wrap_fee"] ) ) {
/* Woocommerce 3.0 + */
$orgPrice = floatval( $value['data']->get_price() );
$value['data']->set_price( $orgPrice + $additionalPrice ); //not adding the $additionalPrice here.
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 99 );
What am I doing wrong here?
Here is the complete clean, tested and working solution based on your code question.
Here I have included your custom field key/value in the cart object for the related cart item, instead of getting the Post value in your calculate_gift_wrap_fee() function.
This way it's not possible to loose the custom field value and the new price calculation is reliable.
I have commented 'gift_wrap_fee' and 'gift_wrap_price' as they are not really needed now (but you can uncomment them if you like).
Here is this code:
// The hidden product custom field
add_action( 'woocommerce_before_add_to_cart_button', 'add_gift_wrap_field' );
function add_gift_wrap_field() {
?>
<input type="hidden" id="price_val" name="added_price" value="100.34">
<?php
}
// Adding the custom field to as custom data for this cart item in the cart object
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
$bool = false;
$data = array();
if( ! empty( $_REQUEST['added_price'] ) ) {
$cart_item_data['custom_data']['added_price'] = $_REQUEST['added_price'];
// Below this 2 values are not really needed (I think)
// (You can uncomment them if needed)
## $cart_item_data['custom_data']['gift_wrap_fee'] = 'YES';
## $cart_item_data['custom_data']['gift_wrap_price'] = 100;
// below statement make sure every add to cart action as unique line item
$cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $data );
}
return $cart_item_data;
}
// Changing the cart item price based on custom field calculation
add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 10, 1 );
function calculate_gift_wrap_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Iterating though cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Continue if we get the custom data for the current cart item
if( ! empty( $cart_item['custom_data'] ) ){
// Get the custom field "added price" value
$added_price = number_format( $cart_item['custom_data']['added_price'], 2 );
// The WC_Product object
$product = $cart_item['data'];
// Get the price (WooCommerce versions 2.5.x to 3+)
$product_price = method_exists( $product, 'get_price' ) ? floatval(product->get_price()) : floatval($product->price);
// New price calculation
$new_price = $product_price + $added_price;
// Set the calculeted price (WooCommerce versions 2.5.x to 3+)
method_exists( $product, 'set_price' ) ? $product->set_price( $new_price ) : $product->price = $new_price;
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works on WooCommerce versions from 2.5.x to 3+.