Change Woocommerce order status programmatically - woocommerce

I am trying to change order status by some conditionals by using woocommerce_thankyou action.
I created some custom order statuses with plugin:
By using this function - nothing happen, the status remain "in hold" and not changed as wishes:
/*after order done*/
function check_and_change_status($order_id){
if ( is_checkout() && is_order_received_page() ) {
$order = wc_get_order( $order_id );
$order_status = $order->get_status();
$product_in_order = false;
$items = $order->get_items();
$count = 0;
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
$is_start_from_product = the_feild('get_an_offer', $product_id);
$the_startFromPrice = the_feild('startFromPrice', $product_id);
$the_winningPrice = the_feild('winningPrice', $product_id);
if ($is_start_from_product && $count == 0) {
$count++;
$price_that_paid = $item->get_total();
if($price_that_paid > $the_startFromPrice && $price_that_paid < $the_winningPrice){
$order->update_status('auctionpending');
}elseif($price_that_paid > $the_winningPrice){
$order->update_status('auctionwon');
}
}elseif ($is_start_from_product && $count > 0) {
/*Do it later*/
}
}
}
}
add_action('woocommerce_thankyou','check_and_change_status');
What i am missing?
The conditional are work well (I have been debugged that), but the order status not changed.

You use the_feild in your foreach loop.
The wordpress function is the_field.
the_field($selector, [$post_id], [$format_value]);
Where $selector is your field name and [$post_id] is the place where your value is saved.
Edit that and try again
$is_start_from_product = the_field('get_an_offer', $product_id);
$the_startFromPrice = the_field('startFromPrice', $product_id);
$the_winningPrice = the_field('winningPrice', $product_id);

Related

Only create coupon on specific product purchase woocommerce

I am trying to create coupon on specific product purchase. Can you please tell me where i am doing wrong
function coupon_code_akki($order_id){
$order = wc_get_order($order_id);
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
}
if ($product_id ='10351'){
$bname= $order->get_billing_first_name();
$bemail= $order->get_billing_email();
$coupon = new WC_Coupon();
$coupon->set_code( $bname . '1990' );
$coupon->set_amount( 1990);
$coupon->set_email_restrictions($bemail)
$coupon->save();
echo 'done';
}
}
Where exactly or at what stage are you using this code?
I think the problem is here:
if ($product_id ='10351'){
In this section, you should check by putting two equals. The equals operator is like this: ==
if ($product_id == '10351'){
And here is the error:
$coupon->set_email_restrictions($bemail)
You should use a semicolon at the end.
function coupon_code_akki($order_id){
$order = wc_get_order($order_id);
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
}
if (!empty($product_id) && $product_id == '10351'){
$bname= $order->get_billing_first_name();
$bemail= $order->get_billing_email();
$coupon = new WC_Coupon();
$coupon->set_code( $bname . '1990' );
$coupon->set_amount( 1990);
$coupon->set_email_restrictions($bemail);
$coupon->save();
echo 'done';
}
}
If you want me to help you, just tell me at what stage you want to create a coupon.

woocommerce conditional email template if product type in order

I try to send a customized email template when a customer has a ticket (custom product type) in cart.
I have the following:
function bc_customer_completed_order_template($template, $template_name, $template_path)
{
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = wc_get_product( $cart_item['product_id'] );
$type = get_class($product);
if ( $type == 'WC_Product_Tickets' && 'customer-completed-order.php' === basename($template) ) {
$template = trailingslashit(plugin_dir_path( __FILE__ )) . 'templates/customer-completed-order.php';
}
}
return $template;
}
add_filter('woocommerce_locate_template', 'bc_customer_completed_order_template', 10, 3);
The conditionals are working (on cart and checkout page for example), but when the order is placed, the new template is not used.
Anybody?
Your email template will look like this:
Code snippets:
// Suppose orders don't have ticket products.
$has_tickets = false;
// Loop order items.
foreach ( $order->get_items() as $item_id => $item ) {
// Get product object from order item.
$_product = $item->get_product();
// Check if the product object is valid and the class is `WC_Product_Tickets`
if ( $_product && 'WC_Product_Tickets' === get_class( $_product ) ) {
// Change the flag.
$has_tickets = true;
// Break the loop as we alreay have true flag.
break;
}
}
// Check if order have tickets items.
if ( $has_tickets ) {
// Load custom email template.
wc_get_template( 'templates/custom-customer-completed-order.php' );
// Return as we don't need the below code.
return;
}
It turned out, although the above solution is correct in its idea, in reality one cannot load a template and make use of the $order without extending the woocommerce email class.
Therefore i loaded the function inside the email template itself and made an if - else statement so for situation A the layout is different then for situation b.
Like so:
$has_tickets = false;
// Loop order items.
foreach ( $order->get_items() as $item_id => $item ) {
// Get product object from order item.
$_product = $item->get_product();
// Check if the product object is valid and the class is `WC_Product_Tickets`
if ( $_product && 'WC_Product_Tickets' === get_class( $_product ) ) {
// Change the flag.
$has_tickets = true;
// Break the loop as we alreay have true flag.
break;
}
}
// Check if order have tickets items.
if ( $has_tickets ) {
do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
//custom email layout here//
}
else{
//Regular email template here
}

Wordpress how to use filter in action hook?

I am getting problem when trying to call add_filter in woocommerce add_action hook. I have to add custom charge when user will register for first time and if he is already logged in and upgrade his membership then i want to remove these charges. Filter is working but it remove charges for first time registration as well upgradation. I am calling it on checkout page but it's not working. This is my code.
function my_remove_signup_fee( $subscription_sign_up_fee, $product ) {
$subscription_sign_up_fee =0;
return $subscription_sign_up_fee;
}
add_action('woocommerce_cart_totals_after_billing', 'action_cart_calculate_totals');
function action_cart_calculate_totals( $cart_object ) {
//echo "<pre>";
//print_r($cart_object);
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( !WC()->cart->is_empty() ):
foreach( WC()->cart->get_cart() as $cart_item ){
$product_id = $cart_item['product_id'];
}
$subfeeArr = get_post_meta( $product_id,'_subscription_sign_up_fee');
if(!empty($subfeeArr)){
$subfee = current($subfeeArr);
}else{
$subfee =0;
}
$current_user = wp_get_current_user();
$userEmail = $current_user->user_email;
$mydb = new wpdb('lbmls_c1lbmlsu','qprn230','lbmls_c1lbmls','mysql01.landbrokermls.com');
$query = "SELECT id FROM users WHERE email = '{$userEmail}' AND com = '1' AND `Coop-Fee` = '1'";
$rows = $mydb->get_results($query,ARRAY_A);
if(!empty($rows)){
$userId = current($rows);
if($userId!=""){
return add_filter( 'woocommerce_subscriptions_product_sign_up_fee', 'my_remove_signup_fee', 10, 2 );
}
}
endif;
}

WooCommerce - Change order status and admin e-mail recipient according to product category

I've been asked to configure a specific WooCommerce behaviour, and I can't escape having to do it with filters. Which I'm not really competent in.
What is supposed to happen, exactly, is that when an order consists only of a product from the "abo" category, it is automatically marked as 'Complete' and the admin mail is sent to a different service.
I've gathered a few examples of code, changing the e-mail recipient, the order status, or making generic changes according to the product category. This is my Frankenstein monster of a code. Both the e-mail change and the order status change failed.
/**
* Change email recipient for admin New Order emails when the order only has products from the 'abo' category
*
* #param string $recipient a comma-separated string of email recipients (will turn into an array after this filter!)
* #param \WC_Order $order the order object for which the email is sent
* #return string $recipient the updated list of email recipients
*/
add_filter( 'woocommerce_email_recipient_new_order', 'dada_conditional_email_recipient', 10, 2 );
function dada_conditional_email_recipient( $recipient, $order ) {
// Bail on WC settings pages since the order object isn't yet set yet
// Not sure why this is even a thing, but shikata ga nai
$page = $_GET['page'] = isset( $_GET['page'] ) ? $_GET['page'] : '';
if ( 'wc-settings' === $page ) {
return $recipient;
}
// just in case
if ( ! $order instanceof WC_Order ) {
return $recipient;
}
$items = $order->get_items();
foreach ( $items as $item ) {
$product = $order->get_product_from_item( $item );
// check if there's an "abo" in the order, then if there's anything else.
if ( is_product() && has_term( 'abo', 'product_cat' ) ) {
$abo_in_order = 'true';
}
if ( is_product() && has_term( 'livre', 'product_cat' ) || has_term( 'revue', 'product_cat' ) || has_term( 'livre', 'product_cat' ) ) {
$abo_alone_in_order = 'false';
}
else {
$abo_alone_in_order = 'true';
}
}
// if there's an 'abo' and nothing else, change the e-mail recipient to dada#sotiaf.fr
if ( ($abo_in_order == 'true')&&($abo_alone_in_order == 'true') ) $recipient = 'dada#sotiaf.fr';
return $recipient;
}
/**
* Autocomplete orders with only an 'abo' product
*/
add_filter( 'woocommerce_payment_complete_order_status', 'dada_abo_order_autocomplete', 10, 2 );
function dada_abo_order_autocomplete( $order_status, $order_id ) {
$order = wc_get_order( $order_id );
if ('processing' == $order_status && ('on-hold' == $order->status || 'pending' == $order->status || 'failed' == $order->status)) {
// just in case
if ( ! $order instanceof WC_Order ) {
return $order_status;
}
$items = $order->get_items();
foreach ( $items as $item ) {
$product = $order->get_product_from_item( $item );
// check if there's an "abo" in the order, then if there's anything else.
if ( is_product() && has_term( 'abo', 'product_cat' ) ) {
$abo_in_order = 'true';
}
if ( is_product() && has_term( 'livre', 'product_cat' ) || has_term( 'revue', 'product_cat' ) || has_term( 'livre', 'product_cat' ) ) {
$abo_alone_in_order = 'false';
}
else {
$abo_alone_in_order = 'true';
}
}
// if there's an 'abo' and nothing else, change the order status to 'completed'
if ( ($abo_in_order == 'true')&&($abo_alone_in_order == 'true') ) $order_status = 'completed';
}
return $order_status;
}
Any idea where the issue comes from?
Thank you,
Joss
You should implement "woocommerce_thankyou" hook for order status update instead of "woocommerce_payment_complete_order_status". Because, your current update order status code will trigerr when any order with completed status is placed. But your requirement is to change status to "Completed".
For adding new email recepient dynamically, you should try this hook : "woocommerce_email_recipient_new_order"
Refer to this : WooCommerce send new order email to customer

How to get current post_id in function.php file

This is my function in function.php file
function getcity(){
global $wpdb;
if($_POST['state'])
{
$id=$_POST['state'];
$district = get_post_meta(get_the_ID() , 'district', true);
var_dump($district);
$result=$wpdb->get_results("SELECT * FROM districts WHERE state_id='$id'");
foreach($result as $row) {
$district_name = $row-
>district_name;
$district_id = $row->district_id;
echo '<option value="'.$district_id.'">'.$district_name.'</option>';
}
}
}
add_action("wp_ajax_nopriv_getcity", "getcity");
add_action("wp_ajax_getcity", "getcity");
I want to get current post id in this function to display selected dropdown value..
Note that $post or get_queried_object_id() do not work until the first query was fired. So these options are available only at the hook template_redirect and later. But functions.php is included much earlier (before the hook after_setup_theme) so this isn't a solution.
A function that should work pretty much anywhere would be:
$url = 'http://' . $_SERVER[ 'HTTP_HOST' ] . $_SERVER[ 'REQUEST_URI' ];
$current_post_id = url_to_postid( $url );
Here is a overview over hook execution order.
As mentioned in the comments url_to_postid may be heavy in some setups, so if your code is executed after template_redirect you better use one of the solutions below as they are most likely much faster than the snippet above:
global $post;
$id = $post->id;
or
$id = get_queried_object_id();
Here is one my function what never fail.
I don't know why WordPress not made something like this before.
/**
* Get current page ID
* #autor Ivijan-Stefan Stipic
* #version 2.0.0
**/
function get_current_page_ID(){
static $current_page_ID;
if(!$current_page_ID) return $current_page_ID;
global $post, $wp_query, $wpdb;
if(!is_null($wp_query) && isset($wp_query->post) && isset($wp_query->post->ID) && !empty($wp_query->post->ID)){
$current_page_ID = $wp_query->post->ID;
} else if(function_exists('get_the_id') && !empty(get_the_id())){
$current_page_ID = get_the_id();
}else if(!is_null($post) && isset($post->ID) && !empty($post->ID))
$current_page_ID = $post->ID;
else if( (isset($_GET['action']) && sanitize_text_field($_GET['action']) == 'edit') && $post = ((isset($_GET['post']) && is_numeric($_GET['post'])) ? absint($_GET['post']) : false))
$current_page_ID = $post;
else if($p = ((isset($_GET['p']) && is_numeric($_GET['p'])) ? absint($_GET['p']) : false))
$current_page_ID = $p;
else if($page_id = ((isset($_GET['page_id']) && is_numeric($_GET['page_id'])) ? absint($_GET['page_id']) : false))
$current_page_ID = $page_id;
else if(!is_admin() && $wpdb)
{
$actual_link = rtrim($_SERVER['REQUEST_URI'], '/');
$parts = explode('/', $actual_link);
if(!empty($parts))
{
$slug = end($parts);
if(!empty($slug))
{
if($post_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT ID FROM {$wpdb->posts}
WHERE
`post_status` = %s
AND
`post_name` = %s
AND
TRIM(`post_name`) <> ''
LIMIT 1",
'publish',
sanitize_title($slug)
)
))
{
$current_page_ID = absint($post_id);
}
}
}
}
else if(!is_admin() && 'page' == get_option( 'show_on_front' ) && !empty(get_option( 'page_for_posts' ))){
$current_page_ID = get_option( 'page_for_posts' );
}
return $current_page_ID;
}
This function check all possible cases and return ID of the current page or false on the fail.

Resources