i created two separate email templates if a customer cancels an order on my store.
Email templates:
Admin: "admin-cancelled-order.php"
Customer: "customer-cancelled-order.php"
Both templates are in the same folder on my server:
public_html/wp-content/themes/hello-theme-child-master/woocommerce/emails/admin-cancelled-order.php
public_html/wp-content/themes/hello-theme-child-master/woocommerce/emails/customer-cancelled-order.php
Both the admin and the customer emails are firing but there both getting the "admin-cancelled-order.php" email template.
In Summary; the customer is getting the admin email template when it should be getting the "customer-cancelled-order.php"
Here is the code:
// Send cancellation email
add_action( 'woocommerce_order_status_changed', 'send_custom_email_notifications', 10, 4 );
function send_custom_email_notifications( $order_id, $old_status, $new_status, $order ){
if ( $new_status == 'cancelled' || $new_status == 'failed' ){
$wc_emails = WC()->mailer()->get_emails();
$order = wc_get_order($order_id);
$customer_email = $order->get_billing_email();
$second_recipient = "info#richtercaterers.com";
$admin_template_html = get_stylesheet_directory() . '/admin-cancelled-order.php';
$admin_template_plain = get_stylesheet_directory() . '/admin-cancelled-order.php';
$customer_template_html = get_stylesheet_directory() . '/customer-cancelled-order.php';
$customer_template_plain = get_stylesheet_directory() . '/customer-cancelled-order.php';
}
if ( $new_status == 'cancelled' ) {
$recipients = $customer_email;
if (!strpos($recipients, $second_recipient)) {
$recipients .= ',' . $second_recipient;
}
$recipients = explode(',', $recipients);
foreach ($recipients as $recipient) {
if ($recipient == $second_recipient) {
$wc_emails['WC_Email_Cancelled_Order']->recipient = $recipient;
if (file_exists($admin_template_html)) {
$wc_emails['WC_Email_Cancelled_Order']->template_html = $admin_template_html;
$wc_emails['WC_Email_Cancelled_Order']->template_plain = $admin_template_plain;
}
} elseif ($recipient == $customer_email) {
$wc_emails['WC_Email_Cancelled_Order']->recipient = $recipient;
if (file_exists($customer_template_html)) {
$wc_emails['WC_Email_Cancelled_Order']->template_html = $customer_template_html;
$wc_emails['WC_Email_Cancelled_Order']->template_plain = $customer_template_plain;
}
}
$wc_emails['WC_Email_Cancelled_Order']->trigger( $order_id );
}
}
Thank you in advance for your help!
Related
I am creating woocommerce plugin to send order details via WhatsApp. Here is my plugin code
add_filter( 'manage_edit-shop_order_columns', 'dvs_whatsapp_msg_list_column' );
function dvs_whatsapp_msg_list_column( $columns ) {
$columns['dvs_show_whatsapp'] = 'WhatsApp';
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'dvs_whatsapp_msg_list_column_content' );
function dvs_whatsapp_msg_list_column_content( $column ) {
global $post;
if ( 'dvs_show_whatsapp' === $column ) {
$order = wc_get_order( $post->ID );
$firstname = $order->get_billing_first_name();
$lastname = $order->get_billing_last_name();
$phone = $order->get_billing_phone();
$ordernum = $order->get_order_number();
$total = $order->get_total();
$payment = $order->get_payment_method_title();
$country = $order->get_billing_country();
$calling_code = WC()->countries->get_country_calling_code($country);
$whatsappnum = $calling_code.$phone;
$msg = 'Hello ' .$firstname. ' ' .$lastname. ', your order #' .$ordernum. ' has been received. The order amount is ' .$total. '. Your payment method is ' .$payment. '. Please contact us if you have any question regarding your order. Thank you.';
echo 'Send WhatsApp';
}
}
This is output
I want when shop manager or admin click the Send Whatsapp link then it will hide the link and show Message sent so shop manager or admin can know the details of this msg is already sent.
Please help.
Javascript is not the way to achieve this. You will use the following instead to hide the link and display "Message sent" once an external link has been clicked:
add_filter( 'manage_edit-shop_order_columns', 'dvs_whatsapp_msg_list_column' );
function dvs_whatsapp_msg_list_column( $columns ) {
$columns['whatsapp'] = __('WhatsApp', 'woocommerce');
return $columns;
}
add_action( 'manage_shop_order_posts_custom_column', 'dvs_whatsapp_msg_list_column_content' );
function dvs_whatsapp_msg_list_column_content( $column ) {
if ( 'whatsapp' === $column ) {
global $the_order;
if( ! $the_order->get_meta('_wapp_sent') ) {
echo '' . __("Send WhatsApp") . '';
}
else {
echo __("Message sent", "woocommerce");
}
}
}
add_action( 'admin_init', 'dvs_redirect_whatsapp_send' );
function dvs_redirect_whatsapp_send() {
global $pagenow;
# Check current admin page.
if ( $pagenow == 'edit.php' && isset($_GET['post_type']) && $_GET['post_type'] == 'shop_order'
&& isset($_GET['send']) && $_GET['send'] == 'dvs_whatsapp' && isset($_GET['order_id']) && $_GET['order_id'] > 0 ) {
$order = wc_get_order( $_GET['order_id'] );
$msg = sprintf( __("Hello %s %s, your order #%s has been received. The order amount is %s. Your payment method is %s. %s", "woocommerce"),
$order->get_billing_first_name(),
$order->get_billing_last_name(),
$order->get_order_number(),
$order->get_total(),
$order->get_payment_method_title(),
__("Please contact us if you have any question regarding your order. Thank you.", "woocommerce")
);
$whatsapp_num = WC()->countries->get_country_calling_code( $order->get_billing_country() ) . $order->get_billing_phone();
update_post_meta( $_GET['order_id'], '_wapp_sent', 'true' ); // Mark order as WhatsApp message sent
wp_redirect( 'https://wa.me/' . $whatsappnum . '?text=' . urlencode($msg) ); // Redirect to WhatsApp sending service
exit;
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
I believe this should do the trick:
jQuery to insert on your page
jQuery('.dvs-whatsapp-btn').click(function(){
jQuery('<span class="link-clicked">Link clicked!</span>').insertAfter('.dvs-whatsapp-btn');
jQuery('.dvs-whatsapp-btn').hide();
});
I'm trying to hook into 'woocommerce_email_recipient_booking_confirmed' to update/add to the recipient field. The link below works perfectly for default WooCommerce emails (and their actions). The action works if I manually type in an email within the action but I need the email to come from the customer input (via a Custom Field on the product page).
I believe it is something to do with class-wc-email-booking-confirmed.php. When I compare it against class-wc-email-customer-completed-order.php
class-wc-email-booking-confirmed.php
public function trigger( $booking_id )
class-wc-email-customer-completed-order.php
public function trigger( $order_id, $order = false )
My code (which I haven't changed from the resource below):
add_filter( 'woocommerce_email_recipient_booking_confirmed', 'additional_customer_email_recipient', 9999, 2 ); // Completed Order
function additional_customer_email_recipient( $recipient, $order ) {
if ( ! is_a( $order, 'WC_Order' ) ) return $recipient; // when I comment this out, an ajax error is thrown. This is why I believe the order object directly accessible yet.
$additional_recipients = array(); // Initializing…
foreach( $order->get_items() as $item_id => $item_data ){
$email = wc_get_order_item_meta( $item_id, 'Email Address', true );
if( ! in_array( $email, $additional_recipients ) && strpos( $recipient, $email ) === false )
$additional_recipients[] = $email;
}
$additional_recipients = implode( ',', $additional_recipients);
if( count($additional_recipients) > 0)
{
$recipient = ','.$additional_recipients;
}
return $recipient;
}
Send Woocommerce Order to email address listed on product page
It was because it wasn't the order object, I just had to call get_order().
$order = $order->get_order();
Code:
add_filter( 'woocommerce_email_recipient_booking_confirmed', 'additional_customer_email_recipient', 10, 2 );
function additional_customer_email_recipient( $recipient, $order ) {
$order = $order->get_order();
$additional_recipients = array();
foreach( $order->get_items() as $item_id => $item_data ){
$email = wc_get_order_item_meta( $item_id, 'Email Address', true );
if( ! in_array( $email, $additional_recipients ) && strpos( $recipient, $email ) === false )
$additional_recipients[] = $email;
}
$additional_recipients = implode( ',', $additional_recipients);
if( count($additional_recipients) > 0)
{
$recipient = $additional_recipients;
}
return $recipient;
}
I have developed a custom code which sends e-mails to the customers based on the category of the product they buy. The problem with my site is one product is having many categories. The script is working correctly, other than that it sends many emails equal to the number of categories a product have. I want it to send only one e-mail per product.
Here is the code:
add_action("woocommerce_order_status_changed", "wcepp_notification_email");
function wcepp_notification_email( $order_id, $checkout = null ) {
global $woocommerce;
$order = new WC_Order( $order_id );
if($order->status === 'processing' ) {
function wcepp_get_custom_email_html( $order, $heading = false, $mailer, $cat_slug ) {
$template = 'emails/woo-custom-emails-per-product-'.$cat_slug.'.php';
return wc_get_template_html( $template, array(
'order' => $order,
'email_heading' => $heading,
'sent_to_admin' => true,
'plain_text' => false,
'email' => $mailer
)
);
}
$liquify_array = array('cutting-agent', 'dabjuice-liquify');
$terpene_array = array('terpene-blends', 'strain-specific', 'hybrid', 'indica', 'sativa', 'terpene-sample-kits', 'hybrid-sample-kit', 'indica-sample-kit', 'sativa-sample-kit');
$isolates_array = array('raw-terpene-isolates', 'alpha', 'beta');
// getting the order products
$items = $order->get_items();
// let's loop through each of the items
foreach ( $items as $item ) {
$categories = get_the_terms( $item['product_id'] , 'product_cat' );
foreach( $categories as $categorie ) {
$cat_slug = $categorie->slug;
if(in_array($cat_slug, $liquify_array)) {
$new_cat_slug = 'liquify';
} elseif(in_array($cat_slug, $terpene_array)) {
$new_cat_slug = 'terpenes';
} elseif(in_array($cat_slug, $isolates_array)) {
$new_cat_slug = 'isolates';
}
if(isset($new_cat_slug)) {
// Create a mailer
$mailer = $woocommerce->mailer();
//Prepare Email
$recipient = $order->billing_email;
if($new_cat_slug == 'liquify') {
$subject = 'Instructions for usage of your Liquify Product';
} elseif($new_cat_slug == 'terpenes') {
$subject = 'Instructions for usage of your Terpenes Product';
} elseif($new_cat_slug == 'isolates') {
$subject = 'Instructions for usage of your Raw Terpenes Isolates';
}
$content = wcepp_get_custom_email_html( $order, $subject, $mailer, $new_cat_slug );
$headers = "Content-Type: text/html\r\n";
//send the email through wordpress
$mailer->send( $recipient, $subject, $content, $headers );
}
}
}
}
}
Any help in this regard will be appraciated.
Your code is outdated since Woocommerce 3 and have many mistakes. If you enable the debug on Wordpress you will get a lot of error messages. Try the following instead that will send an email for each product when it matches with a defined product category:
// Get email content from the custom template
function get_custom_email_content_html( $order, $heading = false, $mailer, $category_slug ) {
$template = 'emails/woo-custom-emails-per-product-'.$category_slug.'.php';
return wc_get_template_html( $template, array(
'order' => $order,
'email_heading' => $heading,
'sent_to_admin' => true,
'plain_text' => false,
'email' => $mailer
)
);
}
// Send a custom email notification for each order item on order processing status change
add_action( 'woocommerce_order_status_changed', 'processing_custom_email_notification', 10, 4 );
function processing_custom_email_notification( $order_id, $status_from, $status_to, $order ) {
if( $status_to === 'processing' ) {
$liquify_array = array('cutting-agent', 'dabjuice-liquify');
$terpene_array = array('terpene-blends', 'strain-specific', 'hybrid', 'indica', 'sativa', 'terpene-sample-kits', 'hybrid-sample-kit', 'indica-sample-kit', 'sativa-sample-kit');
$isolates_array = array('raw-terpene-isolates', 'alpha', 'beta');
// Loop through order items
foreach ( $order->get_items() as $item ) {
$product_category = '';
$categories_slugs = get_the_terms( $item->get_product_id() , 'product_cat', array( 'fields' => 'slugs' ) );
foreach( $categories_slugs as $term_slug ) {
if( in_array( $term_slug, $liquify_array ) ) {
$product_category = 'liquify';
break;
} elseif(in_array( $term_slug, $terpene_array ) ) {
$product_category = 'terpenes';
break;
} elseif(in_array( $term_slug, $isolates_array ) ) {
$product_category = 'isolates';
break;
}
}
if( isset( $product_category ) ) {
// Email subject
if( $product_category == 'liquify' ) {
$subject = __("Instructions for usage of your Liquify Product");
} elseif($product_category == 'terpenes' ) {
$subject = __("Instructions for usage of your Terpenes Product");
} elseif( $product_category == 'isolates' ) {
$subject = __("Instructions for usage of your Raw Terpenes Isolates");
}
$mailer = WC()->mailer(); // Get an instance of the WC_Emails Object
$recipient = $order->get_billing_email(); // Email recipient
$content = get_custom_email_content_html( $order, $subject, $mailer, $product_category ); // Email content (template)
$headers = "Content-Type: text/html\r\n"; // Email headers
// Send the email
WC()->mailer()->send( $recipient, $subject, $content, $headers );
}
}
}
}
It should better work now (but not tested with your product categories).
3 custom email templates should be located in the woocommerce folder > emails subfolder (of the active theme):
woo-custom-emails-per-product-liquify.php
woo-custom-emails-per-product-terpenes.php
woo-custom-emails-per-product-isolates.php
I just want to know if possible to change the email subject if the order have the specific category like (Preorder). I want to put PO at beginning (PO New customer order #0000) then all other order the customer receive the default email subject (New Customer Order #0000).
add_filter('woocommerce_email_subject_new_order', 'change_admin_email_subject', 1, 2);
function change_admin_email_subject( $subject, $order ) {
global $woocommerce;
global $product;
if ( has_term( 'preorder', $product->ID ) ) {
$blogname = wp_specialchars_decode(get_option('blogname'), ENT_QUOTES);
$subject = sprintf( '[%s]New customer order (# %s) from %s %s', $blogname, $order->id, $order->billing_first_name, $order->billing_last_name );
}
return $subject;
}
Note: I just copy this code somewhere.
This can be done this way, making some small changes:
add_filter('woocommerce_email_subject_new_order', 'custom_admin_email_subject', 1, 2);
function custom_admin_email_subject( $subject, $order ) {
$backordered = false;
foreach($order->get_items() as $item_id => $item ){
if ( has_term( 'preorder', 'product_cat' , $item->get_product_id() ) ) {
$backordered = true;
break;
}
}
if ( $backordered ) {
$subject = sprintf( '[PO]New customer order (# %s) from %s %s', $order->get_id(), $order->get_billing_first_name(), $order->get_billing_last_name() );
}
return $subject;
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
Or it can be done this way without a product category, checking that product is backordered:
add_filter('woocommerce_email_subject_new_order', 'custom_admin_email_subject', 1, 2);
function custom_admin_email_subject( $subject, $order ) {
$backordered = false;
foreach($order->get_items() as $item_id => $item ){
$product = $item->get_product();
if( $product->get_backorders() == 'yes' && $product->get_stock_quantity() < 0 ){
$backordered = true;
break;
}
}
if ( $backordered ) {
$subject = sprintf( '[PO]New customer order (# %s) from %s %s', $order->get_id(), $order->get_billing_first_name(), $order->get_billing_last_name() );
}
return $subject;
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
Use this:
function change_admin_email_subject( $subject, $order ) {
// Get all order items
$items = $order->get_items();
$found = false;
// Loop through the items
foreach ( $items as $item ) {
$product_id = $item['product_id'];
// get the categories for current item
$terms = get_the_terms( $product_id, 'product_cat' );
// Loop through the categories to find if 'preorder' exist.
foreach ($terms as $term) {
if($term->slug == 'preorder'){
$subject = 'PO '. $subject;
$found = true;
break;
}
}
if($found == true){
break;
}
}
return $subject;
}
I have a site that allows users(sellers) to enter products on the frontend. When there product sells I would like to email seller to let them know product has been sold.
Heres what I have so far
add_filter ('woocommerce_payment_complete', 'send_seller_email');
function send_seller_email($order_id) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
//foreach loop to get sellers email from order start
foreach ( $items as $item ) {
$product_name = $item->get_name();
$product_id = $item->get_product_id();
$sent_to = wp_get_object_terms( $product_id, 'soldby', false );
$seller_send_email = $sent_to[0]->name;
$seller_email = get_user_by('ID', $seller_send_email);
$email_to_sent_sold_conformation .= $seller_email->user_email;
}//foreach loop to get sellers email end
//Send seller email start
$to = $email_to_sent_sold_conformation;
$subject = 'Sold! ship now: ' . get_the_title($product_id);
$message = '';
$message .= '<p>' . get_the_excerpt($product_id) . '…</p>';
$message .= '<p></p>';
wp_mail($to, $subject, $message );
//Send seller email end
}
I have completely revisited your code:
The main code is in an utility function called by the 2 hooked functions
function hooked in woocommerce_new_order that will trigger paid orders.
function hooked in woocommerce_order_status_changed that will trigger validated orders on update status change.
The code:
// Utility function sending the email notification
function send_seller_email( $order ) {
$data = array();
// Loop through each order item
foreach ( $order->get_items() as $item_id => $item ) {
if( get_post_meta( $order->get_id(), '_sent_to_seller_'.$item_id, true ) )
continue; // Go to next loop iteration
$product_id = $item->get_product_id();
// Untested part
$soldby = wp_get_object_terms( $product_id, 'soldby', false );
if( empty($soldby) ) continue; // Go to next loop iteration
$seller_id = $soldby[0]->name;
$seller = get_user_by( 'ID', $seller_id );
$seller_email = $seller->user_email;
// Set the data in an array (avoiding seller email repetitions)
$data[$seller_email][] = array(
'excerpt' => get_the_excerpt($product_id),
'title' => get_the_title($product_id),
'link' => get_permalink($product_id),
);
// Update order to avoid notification repetitions
update_post_meta( $order->get_id(), '_sent_to_seller_'.$item_id, true );
}
if( count($data) == 0 ) return;
// Loop through custom data array to send mails to sellers
foreach ( $data as $email_key => $values ) {
$to = $email_key;
$subject_arr = array();
$message = '';
foreach ( $values as $value ) {
$subject_arr[] = $value['title'];
$message .= '<p>'.$value['title'].'</p>';
$message .= '<p>'.$value['excerpt'].'…</p>';
}
$subject = 'Sold! ship now: '.implode( ', ', $subject_arr );
// Send email to seller
wp_mail( $to, $subject, $message );
}
exit();
}
add_action('woocommerce_new_order', 'new_order_seller_notification', 10, 1 );
function new_order_seller_notification( $order_id ) {
$order = wc_get_order( $order_id );
if( ! ( $order->has_status('processing') || $order->has_status('completed') ) )
return; // Exit
send_seller_email( $order );
}
add_action( 'woocommerce_order_status_changed', 'order_status_seller_notification', 20, 4 );
function order_status_seller_notification( $order_id, $status_from, $status_to, $order ) {
if( ! ( $status_to == 'processing' || $status_to == 'completed' ) )
return; // Exit
send_seller_email( $order );
}
Code goes in function.php file of your active child theme (or theme).
The code is not really tested, but doesn't make errors. It should work.