I'm building a plugin where a customer(s) is attached to a shop manager. The shop manager can only see orders of customers that are attached to him. The plugin has two parts :
The first one, i already built it, hide all orders that aren't attached to a shop manager. Here's the code in case you want to see how it works :
function before_checkout_create_order($order, $data) {
$store_manager_id = '';
switch ($order->get_user_id()) {
case 34:
$store_manager_id = 18;
break;
case 33:
$store_manager_id = 20;
break;
}
$order->update_meta_data('_store_manager_id', $store_manager_id);
}
add_action('woocommerce_checkout_create_order', 'before_checkout_create_order', 20, 2);
function custom_admin_shop_manager_orders($query) {
global $pagenow;
$qv = &$query->query_vars;
$currentUserRoles = wp_get_current_user()->roles;
$user_id = get_current_user_id();
if (in_array('shop_manager', $currentUserRoles)) {
if ( $pagenow == 'edit.php' &&
isset($qv['post_type']) && $qv['post_type'] == 'shop_order' ) {
// I use the meta key from step 1 as a second parameter here
$query->set('meta_key', '_store_manager_id');
// The value we want to find is the $user_id defined above
$query->set('meta_value', $user_id);
}
}
return $query;
}
add_filter('pre_get_posts', 'custom_admin_shop_manager_orders');
?>
The second part where i need help : I'm trying to have emails only for the shop manager concerned.
Eg : A customer order some products, the shop manager attached to him receives an email about his order but all others shop managers dont receive anything.
If you have any ideas feel free !
Place the following function in your functions.php
Using woocommerce_thankyou hook
function notify_store_manager($order_get_id) {
//Get current order
$order = wc_get_order( $order_get_id );
//Get the manager id for this order
$manager_id = $order->get_meta('_store_manager_id');
//Get manager data
$manager = get_userdata($manager_id);
//Get manager email address
$manager_email = $manager->user_email;
//Build your email info
$order_id = $order->get_id();
$to = $manager_email;
$subject = 'You have new order'.$order_id.'';
$body = 'You have new order with id '.$order_id.'';
$headers = array('Content-Type: text/html; charset=UTF-8');
wp_mail( $to, $subject, $body, $headers );
}
add_action('woocommerce_thankyou', 'notify_store_manager', 10);
Related
I was wondering to know if it is possible to run a WordPress function with a delay of some seconds or minutes.
I use the following snippet to send an email to admin after a new user is registered on my website
add_action( 'user_register', 'registration_email_to_admin', 10, 1 );
function registration_email_to_admin( $user_id ) {
wp_new_user_notification( $user_id );
}
Then I use the following code to filter the email's content
//Filters the contents of the new user notification email sent to the site admin.
add_filter( 'wp_new_user_notification_email_admin', 'custom_wp_new_user_notification_admin_email', 10, 3 );
function custom_wp_new_user_notification_admin_email( $wp_new_user_notification_email, $user, $blogname ) {
//pass user id into a variable
$user_id = $user->id;
//get teams for that user
$teams = wc_memberships_for_teams_get_teams( $user_id );
$teamNames = [];
foreach($teams as $teamName){
array_push($teamNames, $teamName->get_name());
}
$teamNamesString = implode (',' , $teamNames);
$wp_new_user_notification_email['subject'] = sprintf( '[%s] New user registered. User ID = %s', $blogname, $user->id );
$wp_new_user_notification_email['message'] = sprintf( "%s ( %s ) has registered to the website %s.", $user->user_login, $user->user_email, $blogname ) . "\r\n\r\n";
$wp_new_user_notification_email['message'] .= sprintf(__('Username: %s'), $user->user_login) . "\r\n";
$wp_new_user_notification_email['message'] .= sprintf(__('Email: %s'), $user->user_email) . "\r\n";
$wp_new_user_notification_email['message'] .= sprintf(__('ID: %s'), $user->id) . "\r\n";
$wp_new_user_notification_email['message'] .= sprintf(__('Team Name: %s'), $teamNamesString) . "\r\n";
$wp_new_user_notification_email['headers'] = "From: Members Website <info#test.com> \n\r cc: GeorgeFR <test#yahoo.com>";
return $wp_new_user_notification_email;
}
On all the above, everything works well except the last append to the message
$wp_new_user_notification_email['message'] .= sprintf(__('Team Name: %s'), $teamNamesString) . "\r\n";
Using the WooCommerce Memberships for Teams plugin, it seems that the new user is being assigned to the team that has been invited to after his/her registration. That being said, the variable $teamNamesString is always empty on my email content.
So, is it possible to run all the above with some delay, making sure that the team has been assigned to the new user before I send the email? It is important for me to include the team's name to the email for business management purposes.
I was finally able to find the fix here.
Using the Woo Memberships and Woo Teams for Memberships plugins, we have 3 different team roles on our website. Owners, Managers, and Members. Also, we are using Woo Subscriptions in combination with Woo Memberships. So, every time a new subscription purchase comes, the purchaser will create a team and become the owner of that team.
The codes that worked are the following:
For Owners (used the woocommerce_subscription_status_active action from Woo Subscriptions):
//fires after purchases
function send_admin_email_with_owner_data_after_purchase( $subscription ) {
// Get the user in the order
$user_id = $subscription->get_user_id();
// Get the products in the order
$items = $subscription->get_items();
foreach( $items as $item ) {
$product = $item->get_product();
$product_id = $product->get_id();
if ($product_id == "8865") {
wp_new_user_notification( $user_id );
}
}
}
add_action( 'woocommerce_subscription_status_active', 'send_admin_email_with_owner_data_after_purchase', 10 );
For Managers and Members (used the wc_memberships_user_membership_created action from Woo Memberships):
//fires after acceptance of invitations to teams (in my case)
function send_admin_email_with_member_data( $plan, $args ) {
$user_id = $args['user_id'];
$memberArgs = array (
$status => "any",
$role => "manager,member"
);
//get teams for that user
$teams = wc_memberships_for_teams_get_teams( $user_id, $memberArgs );
if ( $args['is_update'] = true && ! empty( $teams ) ) {
wp_new_user_notification( $user_id );
}
}
add_action( 'wc_memberships_user_membership_created', 'send_admin_email_with_member_data', 20, 2 );
I am glad I found a way here. Thank you all for your help!
I need help with a custom email hook for woocommerce.
I am trying to send a different email depending on product ID whenever a product is completed.
My code, which is not working, is as follows:
/**************
DIFFERENT MESSAGES FOR DIFFERENT PRODUCTS
****************/
//hook our function to the new order email
add_action('woocommerce_email_order_details', 'uiwc_email_order_details_products', 1, 4);
function uiwc_email_order_details_products($order, $admin, $plain, $email) {
$status = $order->get_status();
// checking if it's the order status we want
if ( $status == "completed" ) {
$items = $order->get_items();
if ( $item['product_id'] == "3181") {
echo __( '<strong>IMPORTANT - NEXT STEP:</strong><br>To get started, please follow this link to complete the Policies form.<br><br>This is a really important first step, and only takes about 5 minutes. After completeing the Policies form, you will receive additional instructions on next steps.<br><br>Congratulations! Let your journey begin.<br><br>', 'uiwc' );
}
elseif ( $item['product_id'] == "3223") {
echo __( '<strong>IMPORTANT - NEXT STEP:</strong><br>Differnet product so differenct email....<br><br>', 'uiwc' );
}
}
}
Any suggestions is greatly appreciated
There is some mistakes in your code, instead try the following
//hook our function to the new order email
add_action( 'woocommerce_email_order_details', 'custom_email_order_details', 4, 4 );
function custom_email_order_details( $order, $admin, $plain, $email ) {
$domain = 'woocommerce';
// checking if it's the order status we want
if ( $order->has_status('completed') ) {
foreach( $order->get_items() as $item ){
if ( $item->get_product_id() == '3181' ) {
echo __( '<strong>IMPORTANT - NEXT STEP:</strong><br>To get started, please follow this link to complete the Policies form.<br><br>This is a really important first step, and only takes about 5 minutes. After completeing the Policies form, you will receive additional instructions on next steps.<br><br>Congratulations! Let your journey begin.<br><br>', $domain );
break;
}
elseif ( $item->get_product_id() == '3223' ) {
echo __( '<strong>IMPORTANT - NEXT STEP:</strong><br>Differnet product so differenct email....<br><br>', $domain );
break;
}
}
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
I have completed a woocommerce website for a client. As per the client requirement I got an issue. My client wants their agents just need to able to search for the orders but they should not able to edit any of the order or they should not see any other option. Agents should see all the order details like phone number, email and complete billing address but they should not able to edit anything.
I have tried few user role editors none of them giving that option.
Note : All the orders are guest orders only!
Please let me know if you have any idea how to achieve this.
Try this in your theme functions.php
//mydomain.com/my-account/view-order/xxxx - any order number here
function my_customer_has_capability( $allcaps, $caps, $args ) {
if ( isset( $caps[0] ) ) {
switch ( $caps[0] ) {
case 'view_order' :
$user_id = $args[1];
$order = wc_get_order( $args[2] );
if ( $order && $user_id == $order->user_id || my_get_current_user_role() == 'editor') {
$allcaps['view_order'] = true;
}
break;
}
}
return $allcaps;
}
add_filter( 'user_has_cap', 'my_customer_has_capability', 10, 3 );
function my_get_current_user_role() {
$current_user = wp_get_current_user();
if ( !($current_user instanceof WP_User) )
return;
if( empty($current_user->roles[0]) )
return false;
$role = ($current_user->roles[0]);
return (string)$role;
}
With WooCommerce I use a special theme that handle bookings for motorbikes and scooters rental service. I want to get the order related data. I am trying to send an SMS when an email notification is sent to customer for completed, on hold, pending and **processing** order status.
I have use the code below for instance that output the data I need in SMS:
$order = new WC_Order($order_id);
$status = $order->get_status(); // order status
if( 'completed' == $status || 'processing' == $status || 'pending' == $status || 'on-hold' == $status ){
$user_phone = get_post_meta($order_id, '_billing_phone', true);
foreach ($order->get_items() as $item_id => $item) {
$product_id = $order->get_item_meta($item_id, '_product_id', true); // product ID
$product_name = get_post($product_id)->post_title; // Product description
// Related Booking data to insert in SMS
$book_check_in = $order->get_item_meta( $item_id, '_st_check_in', true );
$book_check_out = $order->get_item_meta( $item_id, '_st_check_out', true );
$book_pick_up = $order->get_item_meta( $item_id, '_st_pick_up', true );
$book_drop_off = $order->get_item_meta( $item_id, '_st_drop_off', true );
}
// Send SMS in SMS API
file_get_contents("http://144.76.39.175/api.php?username=xxxxxxxxxxx&password=xxxxxxxxxxx&route=1&message%5B%5D=The+message&sender=NBWREN&mobile%5B%5D=xxxxxxxxxxx");
}
This is not working. Where should I hook this code? I tried different templates and all I got were some 500 errors or simply nothing happened.
Please give me some help.
Thanks
You can use a custom function hooked in woocommerce_email_order_details hook, using included $order and $email objects.
You will be able to rearrange the message as you like, as this is just an example.
I have commented this code to make you understand how it works:
add_action('woocommerce_email_order_details', 'send_sms_on_email_notifications', 10, 4);
function send_sms_on_email_notifications($order, $sent_to_admin, $plain_text, $email){
$order_id = $order->id; // get the order ID for Order object
$email_id = $email->id; // get the email ID for Email object
$order_status = $order->get_status(); // Get order Status
// Array of Email IDs to avoid Admin email notifications (SMS sent twice on some notifications)
$emails_ids_exceptions = array('new_order', 'failed_order', 'customer_invoice', 'customer_note');
// Your targeted order status
$order_statuses = array('completed', 'processing', 'on-hold', 'pending');
$send_the_sms = false;
// Just for your targeted order statuses
if( in_array( $order_status, $order_statuses ) ):
// iterating in the order items
foreach($order->get_items() as $item_id => $item):
$prod_id = $order->get_item_meta( $item_id, '_product_id', true ); // product ID
$prod_name = get_post($prod_id)->post_title; // Product Name
$mobile = get_post_meta($order_id, '_billing_phone', true); // mobile phone
// Related Booking data to insert in SMS
$check_in = $order->get_item_meta( $item_id, '_st_check_in', true );
$check_out = $order->get_item_meta( $item_id, '_st_check_out', true );
$pick_up = $order->get_item_meta( $item_id, '_st_pick_up', true );
$drop_off = $order->get_item_meta( $item_id, '_st_drop_off', true );
// stoping the loop (just for one item)
break;
endforeach;
// Limiting to customer email notifications
if( !in_array( $email_id, $emails_ids_exceptions ) )
{
// inserting the order data (variables) in the message
$text = "Your order $order_id with $status status, for $prod_name. Your booking details: Check in time: $check_in, Check out Time: $check_out, Pick up $pick_up and drop of Time is $drop_off";
$send_the_sms = true;
}
// TRIGGERING THE SMS
if($send_the_sms)
{
// Replacing spaces by '+' in the message
$message = str_replace(' ', '+', $text);
// Inserting the message and the user number phone in the URL
$url = "http://144.76.39.175/api.php?username=xxxxxxxxxxx&password=xxxxxxxxxxx&route=1&message%5B%5D=$message&sender=NBWREN&mobile%5B%5D=$mobile";
// Triggering the SMS
file_get_contents($url);
}
endif;
}
This code will work for the first item of the order, assuming that people rent one bike or one scooter at the time.
The code is mainly tested, but I can't guaranty the triggered SMS as I can't test it on your SMS API. I hope this will work… Let me know.
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
I am creating an online shop with WooCommerce and I'm adding a function which will update the bonus point to my database into absract-wc-payment-gateway.php.
Here is what I am doing:
Firstly, on the checkout page, the users will click the place order button and then the method will get the users bonus points and minus the bonus points with the get-total(), and then update to the database and go to the thank you page.
Then, the thank you page will get the user's bonus points from the database. And I set the bonus points value to 2000. So in this case, the bonus points should be minus by total Points($50.00)
Here is my code. It will be ran when the user clicks the place order button:
global $woocommerce;
$order = new WC_Order($order_id);
$total = $order->get_total();
$bonusPoint -= (int)$total; //minus total price and calculate the latest bonus point
$updateSql = "UPDATE userdata02 SET bonusPoint ='" .$bonusPoint. "' WHERE userID = 2147483647";
mysqli_query($link, $updateSql);// update to an int column
if(mysqli_query($link, $updateSql)) {
echo "Record updated successfully";
} else {
echo "Error update record: <>" . mysqli_error($link);
}
Call the method when the user clicks place button:
public function get_return_url( $order = null ) {
if ( $order ) {
//$message = "wrong answer";
//echo "<script type='text/javascript'>alert('$message');</script>";
$return_url = $order->get_checkout_order_received_url();
} else {
$return_url = wc_get_endpoint_url( 'order-received', '', wc_get_page_permalink( 'checkout' ) );
}
if ( is_ssl() || get_option('woocommerce_force_ssl_checkout') == 'yes' ) {
$return_url = str_replace( 'http:', 'https:', $return_url );
}
self::reducePoints(); //Call reducePoints();
return apply_filters( 'woocommerce_get_return_url', $return_url, $order );
}
The source code: reducePoints() lines 89 from abstract-WC-Payment-Gateway.php
The get_total() doesn't work and it returns zero.
What I am doing wrong?
You need to create an object for $order to use it with get_total(). Try this:
global $woocommerce;
$order = new WC_Order($order_id);
$total = $order->get_total(); //Get the total price of the order.
$bonusPoints -= (int)$total; //calculate the new bonusPoints
Update1: This is just solving the internal data error. We need to get the $order_id to get it work…
Note: You can remove global $woocommerce;before $order = new WC_Order($order_id); because is already included in public function reducePoints( ){
Update2 - The good track:
Remove my code:
global $woocommerce;
$order = new WC_Order($order_id);
Then at line 89 of your code just add $order in:
public function reducePoints( $order ){
global $woocommerce;
// ...
Really happy that this works… It was a long search...