Change product stock availability texts in Woocommerce - php

I am trying to change the in stock text next to the quantity available in woocommerce. I am using the stock management in product variations.
I tried this code below:
// change stock text
add_filter( 'woocommerce_get_availability', 'wcs_custom_get_availability', 1, 2);
function wcs_custom_get_availability( $availability, $variation ) {
// Change In Stock Text
if ( $variation->is_in_stock() ) {
$availability['availability'] = __('Available!', 'woocommerce');
}
// Change Out of Stock Text
if ( ! $variation->is_in_stock() ) {
echo '-------------------------';
echo __('Sold Out', 'woocommerce');
$availability['availability'] = __('Sold Out', 'woocommerce');
}
return $availability;
}
The code above changes the text but it does not pull in the stock quantity number from the variation stock manager.

The following code will handle all cases including the stock amount display with your custom texts:
add_filter( 'woocommerce_get_availability_text', 'customizing_stock_availability_text', 1, 2);
function customizing_stock_availability_text( $availability, $product ) {
if ( ! $product->is_in_stock() ) {
$availability = __( 'Sold Out', 'woocommerce' );
}
elseif ( $product->managing_stock() && $product->is_on_backorder( 1 ) )
{
$availability = $product->backorders_require_notification() ? __( 'Available on backorder', 'woocommerce' ) : '';
}
elseif ( $product->managing_stock() )
{
$availability = __( 'Available!', 'woocommerce' );
$stock_amount = $product->get_stock_quantity();
switch ( get_option( 'woocommerce_stock_format' ) ) {
case 'low_amount' :
if ( $stock_amount <= get_option( 'woocommerce_notify_low_stock_amount' ) ) {
/* translators: %s: stock amount */
$availability = sprintf( __( 'Only %s Available!', 'woocommerce' ), wc_format_stock_quantity_for_display( $stock_amount, $product ) );
}
break;
case '' :
/* translators: %s: stock amount */
$availability = sprintf( __( '%s Available!', 'woocommerce' ), wc_format_stock_quantity_for_display( $stock_amount, $product ) );
break;
}
if ( $product->backorders_allowed() && $product->backorders_require_notification() ) {
$availability .= ' ' . __( '(can be backordered)', 'woocommerce' );
}
}
else
{
$availability = '';
}
return $availability;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Related

Add custom stock status in WooCommerce treated as out of stock

I created 2 new custom stock statuses:
Out of stock (Permanent)
Out of stock (Supplier)
As you can guess, I want them both to be treated as out of stock.
I used some extra code to hide the products with these custom statuses from the front end but I can not hide them from the ajax search (live) and also someone can add the product in cart.
(I use the Flatsome theme and the live search is from there)
Based on: How to add custom stock status to products in WooCommerce 4+
& Hide all products with a specific stock status from WooCommerce catalog, this is my code attempt:
// Add new stock status options
function filter_woocommerce_product_stock_status_options( $status ) {
// Add new statuses
$status['permanent'] = __( 'Out of stock (Permanent)', 'woocommerce' );
$status['supplier'] = __( 'Out of stock (Supplier)', 'woocommerce' );
return $status;
}
add_filter( 'woocommerce_product_stock_status_options', 'filter_woocommerce_product_stock_status_options', 10, 1 );
// Availability text
function filter_woocommerce_get_availability_text( $availability, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'permanent':
$availability = __( 'Out of stock (Permanent)', 'woocommerce' );
break;
case 'supplier':
$availability = __( 'Out of stock (Supplier)', 'woocommerce' );
break;
}
return $availability;
}
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );
// Availability CSS class
function filter_woocommerce_get_availability_class( $class, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'permanent':
$class = 'permanent';
break;
case 'supplier':
$class = 'supplier';
break;
}
return $class;
}
add_filter( 'woocommerce_get_availability_class', 'filter_woocommerce_get_availability_class', 10, 2 );
// Admin stock html
function filter_woocommerce_admin_stock_html( $stock_html, $product ) {
// Simple
if ( $product->is_type( 'simple' ) ) {
// Get stock status
$product_stock_status = $product->get_stock_status();
// Variable
} elseif ( $product->is_type( 'variable' ) ) {
foreach( $product->get_visible_children() as $variation_id ) {
// Get product
$variation = wc_get_product( $variation_id );
// Get stock status
$product_stock_status = $variation->get_stock_status();
}
}
// Stock status
switch( $product_stock_status ) {
case 'permanent':
$stock_html = '<mark class="permanent" style="background:transparent none;color:#33ccff;font-weight:700;line-height:1;">' . __( 'Out of stock (Permanent)', 'woocommerce' ) . '</mark>';
break;
case 'supplier':
$stock_html = '<mark class="supplier" style="background:transparent none;color:#cc33ff;font-weight:700;line-height:1;">' . __( 'Out of stock (Supplier)', 'woocommerce' ) . '</mark>';
break;
}
return $stock_html;
}
add_filter( 'woocommerce_admin_stock_html', 'filter_woocommerce_admin_stock_html', 10, 2 );
//hide specific stock status
add_action( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 1000 );
function custom_product_query_meta_query( $meta_query ) {
if ( ! is_admin() ) {
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'permanent',
'compare' => '!=',
);
}
if ( ! is_admin() ) {
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'supplier',
'compare' => '!=',
);
}
return $meta_query;
}
Any advice on how to handle both custom stock statuses as out of stock?
Since you indicate in your question that your custom stock statuses should contain the same functionality as the current 'outofstock' status, you can instead of rewrite/reuse all existing functionality of the 'outofstock' status for your custom stock statuses, use a workaround.
This will offer a simple solution, since otherwise you would have to overwrite some template files in addition to writing custom code.
The workaround can be applied as follows:
Step 1) add an extra custom field for your custom statuses, we will add this field under the existing stock status field:
// Add custom field
function action_woocommerce_product_options_stock_status() {
// Custom stock status
$options = array(
'empty' => __( 'N/A', 'woocommerce' ),
'permanent' => __( 'Permanent', 'woocommerce' ),
'supplier' => __( 'Supplier', 'woocommerce' ),
);
woocommerce_wp_select(
array(
'id' => '_custom_stock_status',
'wrapper_class' => 'stock_status_field hide_if_variable hide_if_external hide_if_grouped',
'label' => __( 'Custom stock status', 'woocommerce' ),
'options' => $options,
'desc_tip' => true,
'description' => __( 'Your description', 'woocommerce' ),
)
);
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10 );
// Save custom field
function action_woocommerce_admin_process_product_object( $product ) {
// Isset
if ( isset( $_POST['_custom_stock_status'] ) ) {
// Update
$product->update_meta_data( '_custom_stock_status', sanitize_text_field( $_POST['_custom_stock_status'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
Result:
Step 2) when the product is 'out of stock', we will check whether a custom stock status has been set. If this is the case, we will visually change the text using the code below, so that the customer can see the new status. In the background/backend, however, the 'out of stock' status is still used and therefore automatically also the existing functionality:
// Availability text
function filter_woocommerce_get_availability_text( $availability, $product ) {
// Only for 'outofstock'
if ( $product->get_stock_status() == 'outofstock' ) {
// Get custom stock status
$custom_stock_status = $product->get_meta( '_custom_stock_status' );
// Compare and apply new text
if ( $custom_stock_status == 'permanent' ) {
$availability = __( 'Out of stock (Permanent)', 'woocommerce' );
} elseif ( $custom_stock_status == 'supplier' ) {
$availability = __( 'Out of stock (Supplier)', 'woocommerce' );
}
}
return $availability;
}
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );

Get tax information in displayed formatted subtotal in WooCommerce

Right now i am displaying the tax for all hte prices like total and shipping, now i have the requirement to add the same tax values for the subtotals as well as shown in the following image
I have found nothing related to this but for the cart page to add new field with the others, SO actually i want to add this tax information with the subtotal field.
Show subtotal excl. tax, add subtotal tax as separate row on Woocommerce checkout
To display in cart subtotal (orders and notifications) like "71,540.20€ (includes 11400,00€ VAT)", you can try to use the following:
// Cart and checkout (for display including taxes - not compound)
add_filter('woocommerce_cart_subtotal', 'wc_cart_subtotal_incl_tax_amount_filter', 10, 3 );
function wc_cart_subtotal_incl_tax_amount_filter( $cart_subtotal, $compound, $cart ) {
if ( wc_tax_enabled() && $cart->get_subtotal_tax() > 0 && ! $compound ) {
$subtotal_tax = wc_price( $cart->get_subtotal_tax() );
$cart_subtotal = wc_price( $cart->get_subtotal() + $cart->get_subtotal_tax() );
$tax_label = in_array( WC()->countries->get_base_country(), array_merge( WC()->countries->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ), true ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
$cart_subtotal .= sprintf( ' <small>' . esc_html__( '(includes %s %s)', 'woocommerce' ) . '</small>', $subtotal_tax, $tax_label );
}
return $cart_subtotal;
}
// Orders and emails (for display including taxes - not compound)
add_filter('woocommerce_order_subtotal_to_display', 'wc_order_subtotal_incl_tax_amount_filter', 10, 3 );
function wc_order_subtotal_incl_tax_amount_filter( $subtotal, $compound, $order ) {
if ( wc_tax_enabled() && $order->get_total_tax() > 0 && ! $compound ) {
$subtotal_tax = $subtotal = 0; // Initializing
// Loop through order items
foreach ( $order->get_items() as $item ) {
$subtotal += $item->get_subtotal() + $item->get_subtotal_tax();
$subtotal_tax += $item->get_subtotal_tax();
}
$subtotal = wc_price( $subtotal, array( 'currency' => $order->get_currency() ) );
$subtotal_tax = wc_price( $subtotal_tax, array( 'currency' => $order->get_currency() ) );
$tax_label = in_array( WC()->countries->get_base_country(), array_merge( WC()->countries->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ), true ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
$subtotal .= sprintf( ' <small>' . esc_html__( '(includes %s %s)', 'woocommerce' ) . '</small>', $subtotal_tax, $tax_label );
}
return $subtotal;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

How to add custom stock status to products in WooCommerce 4+

I am using the following code to add new stock statuses in WooCommerce 4+
The new statuses are:
Preorder
Contact us
function add_custom_stock_type() {
?>
<script type="text/javascript">
jQuery(function(){
jQuery('._stock_status_field').not('.custom-stock-status').remove();
});
</script>
<?php
woocommerce_wp_select( array( 'id' => '_stock_status', 'wrapper_class' => 'custom-stock-status', 'label' => __( 'Stock status', 'woocommerce' ), 'options' => array(
'instock' => __( 'Available', 'woocommerce' ), //changed the name
'outofstock' => __( 'Sold out', 'woocommerce' ), //changed the name
'onbackorder' => __( 'Preorder : Pending Distributor release', 'woocommerce' ), //changed the name
'contact' => __( 'Contact us for Availability', 'woocommerce' ), //added new one
'preorder' => __( 'On Preorder: Pending Distributor release', 'woocommerce' ), //added new one
), 'desc_tip' => true, 'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ) ) );
}
add_action('woocommerce_product_options_stock_status', 'add_custom_stock_type');
function save_custom_stock_status( $product_id ) {
update_post_meta( $product_id, '_stock_status', wc_clean( $_POST['_stock_status'] ) );
}
add_action('woocommerce_process_product_meta', 'save_custom_stock_status',99,1);
function woo_add_custom_general_fields_save_two( $post_id ){
// Select
$woocommerce_select = $_POST['_stock_status'];
if( !empty( $woocommerce_select ) )
update_post_meta( $post_id, '_stock_status', esc_attr( $woocommerce_select ) );
else
update_post_meta( $post_id, '_stock_status', '' );
}
function woocommerce_get_custom_availability( $data, $product ) {
switch( $product->stock_status ) {
case 'instock':
$data = array( 'availability' => __( 'Available', 'woocommerce' ), 'class' => 'in-stock' ); //changed name
break;
case 'outofstock':
$data = array( 'availability' => __( 'Sold Out', 'woocommerce' ), 'class' => 'out-of-stock' ); //changed name
break;
case 'onbackorder':
$data = array( 'availability' => __( 'Preorder : Pending Distributor release', 'woocommerce' ), 'class' => 'onbackorder' ); //changed name
break;
case 'contact':
$data = array( 'availability' => __( 'Contact us for Availability', 'woocommerce' ), 'class' => 'contact' ); //added new one
break;
case 'preorder':
$data = array( 'availability' => __( 'On Preorder : Pending Distributor release', 'woocommerce' ), 'class' => 'preorder' ); //added new one
break;
}
return $data;
}
add_action('woocommerce_get_availability', 'woocommerce_get_custom_availability', 10, 4);
Works:
Backend: The new status is added in the dropdown menu, I can select the status I want
Does not work:
Front end: on single product page is not showing the correct status
Backend: Display the new status on the admin products list table
Someone who can assist me with this?
Last update: 04/22 - Tested in WordPress 5.9.2 & WooCommerce 6.3.1
Code goes in functions.php file of the active child theme (or active theme).
Use woocommerce_product_stock_status_options
instead of woocommerce_product_options_stock_status.
This way you can immediately add a status instead of replace the existing dropdown
Also use woocommerce_get_availability_text & woocommerce_get_availability_class
opposite woocommerce_get_availability.
This way you don't have to add the existing statuses again
// Add new stock status options
function filter_woocommerce_product_stock_status_options( $status ) {
// Add new statuses
$status['pre_order'] = __( 'Pre order', 'woocommerce' );
$status['contact_us'] = __( 'Contact us', 'woocommerce' );
return $status;
}
add_filter( 'woocommerce_product_stock_status_options', 'filter_woocommerce_product_stock_status_options', 10, 1 );
// Availability text
function filter_woocommerce_get_availability_text( $availability, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'pre_order':
$availability = __( 'Pre order', 'woocommerce' );
break;
case 'contact_us':
$availability = __( 'Contact us', 'woocommerce' );
break;
}
return $availability;
}
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );
// Availability CSS class
function filter_woocommerce_get_availability_class( $class, $product ) {
// Get stock status
switch( $product->get_stock_status() ) {
case 'pre_order':
$class = 'pre-order';
break;
case 'contact_us':
$class = 'contact-us';
break;
}
return $class;
}
add_filter( 'woocommerce_get_availability_class', 'filter_woocommerce_get_availability_class', 10, 2 );
Use woocommerce_admin_stock_html to display the new stock status on the admin products list table
// Admin stock html
function filter_woocommerce_admin_stock_html( $stock_html, $product ) {
// Simple
if ( $product->is_type( 'simple' ) ) {
// Get stock status
$product_stock_status = $product->get_stock_status();
// Variable
} elseif ( $product->is_type( 'variable' ) ) {
foreach( $product->get_visible_children() as $variation_id ) {
// Get product
$variation = wc_get_product( $variation_id );
// Get stock status
$product_stock_status = $variation->get_stock_status();
/*
Currently the status of the last variant in the loop will be displayed.
So from here you need to add your own logic, depending on what you expect from your custom stock status.
By default, for the existing statuses. The status displayed on the admin products list table for variable products is determined as:
- Product should be in stock if a child is in stock.
- Product should be out of stock if all children are out of stock.
- Product should be on backorder if all children are on backorder.
- Product should be on backorder if at least one child is on backorder and the rest are out of stock.
*/
}
}
// Stock status
switch( $product_stock_status ) {
case 'pre_order':
$stock_html = '<mark class="pre-order" style="background:transparent none;color:#33ccff;font-weight:700;line-height:1;">' . __( 'Pre order', 'woocommerce' ) . '</mark>';
break;
case 'contact_us':
$stock_html = '<mark class="contact-us" style="background:transparent none;color:#cc33ff;font-weight:700;line-height:1;">' . __( 'Contact us', 'woocommerce' ) . '</mark>';
break;
}
return $stock_html;
}
add_filter( 'woocommerce_admin_stock_html', 'filter_woocommerce_admin_stock_html', 10, 2 );
Optional: if desired, the custom stock status can be used in hooks where you already have access to the $product object or you can use global $product.
1) No access to the $product object, use global $product as is the case for example with the woocommerce_shop_loop_item_title or the woocommerce_single_product_summary hook
function woocommerce_my_callback() {
// An example based on global $product
// Get the global product object
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get stock status
$product_stock_status = $product->get_stock_status();
// Use this line during testing, delete afterwards!
echo '<p style="color:red;font-size:20px;">DEBUG INFORMATION = ' . $product_stock_status . '</p>';
// Compare
if ( $product_stock_status == 'My custom stock status' ) {
// Etc..
}
}
}
add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_my_callback', 10 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_my_callback', 10 );
2) Access to the $product object, because it's passed by default to the callback function. As is the case for example with the woocommerce_get_price_html hook
function filter_woocommerce_get_price_html( $price, $product ) {
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get stock status
$product_stock_status = $product->get_stock_status();
// Use this line during testing, delete afterwards!
echo '<p style="color:red;font-size:20px;">DEBUG INFORMATION = ' . $product_stock_status . '</p>';
// Compare
if ( $product_stock_status == 'My custom stock status' ) {
// Etc..
// $price .= ' my text';
}
}
return $price;
}
add_filter( 'woocommerce_get_price_html', 'filter_woocommerce_get_price_html', 10, 2 );
In addition to filters provided by 7uc1f3r woocommerce_product_export_product_column_stock_status filter is required to display custom stock status in exported products CSV file:
function add_custom_stock_csv_data( $_, $product ) {
$status = $product->get_stock_status( 'edit' );
switch( $status ) {
case 'pre_order':
case 'contact_us':
return $status;
case 'onbackorder':
return 'backorder';
case 'instock':
return 1;
default:
return 0;
}
}
add_filter( 'woocommerce_product_export_product_column_stock_status', 'add_custom_stock_csv_data', 10, 2 );

Alter specifically coupon validation minimum amount filter hook in Woocommerce

I want to Alter function validate_coupon_minimum_amount() adding a condition that if a user use coupon "refresh18", check to see if subtotal in cart for a product category is greater than the coupon's minimum amount.
How could I do that?
Here is my code below that doesn't work:
function check_minimum_parts_amount_in_cart($coupon) {
$cart_parts_subtotal = 0;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
$product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );
$terms = get_the_terms( $product_id, 'product_cat' );
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) && has_term( 'ice-shaving-parts', 'product_cat', $product_id ) ) {
//echo '<pre>' . print_r($cart_item , 1) . '</pre>';
//echo $cart_item['quantity'];
$cart_parts_subtotal = $cart_parts_subtotal + ( $_product->get_price() * $cart_item['quantity'] );
}
}
$subtotal = wc_remove_number_precision( $this->get_object_subtotal() );
if( $coupon->get_name() == 'refresh2018' ){
if( $coupon->get_minimum_amount() > 0 && apply_filters( 'woocommerce_coupon_validate_minimum_amount', $coupon->get_minimum_amount() > $cart_parts_subtotal, $coupon, $cart_parts_subtotal )){
/* translators: %s: coupon minimum amount */
throw new Exception( sprintf( __( 'The minimum spend for this coupon is %s.', 'woocommerce' ), wc_price( $coupon->get_minimum_amount() ) ), 108 );
}else{
return true;
}
}else{
if ( $coupon->get_minimum_amount() > 0 && apply_filters( 'woocommerce_coupon_validate_minimum_amount', $coupon->get_minimum_amount() > $subtotal, $coupon, $subtotal )) {
/* translators: %s: coupon minimum amount */
throw new Exception( sprintf( __( 'The minimum spend for this coupon is %s.', 'woocommerce' ), wc_price( $coupon->get_minimum_amount() ) ), 108 );
}else{
return true;
}
}
}
add_filter('validate_coupon_minimum_amount', 'check_minimum_parts_amount_in_cart');
Updated:
Since Woocommerce 3.2+ use instead woocommerce_coupon_validate_minimum_amount filter hook… So you should try this revisited code (Where you will have to set your product category):
add_filter( 'woocommerce_coupon_validate_minimum_amount', 'custom_check_minimum_amount_in_cart', 10, 3 );
function custom_check_minimum_amount_in_cart( $valid, $coupon, $subtotal ) {
// HERE below your settings (Coupon code and product category)
$coupon_code = 'refresh18';
$product_category = 'clothing'; // <== To be replaced by your targeted product category
$cat_subtotal = 0;
foreach ( WC()->cart->get_cart() as $cart_item ){
if( has_term( $product_category, 'product_cat', $cart_item['product_id'] ) )
$cat_subtotal += $cart_item['line_subtotal'];
}
if( $coupon->get_code() == $coupon_code && $coupon->get_minimum_amount() > $cat_subtotal ){
throw new Exception( sprintf( __( 'The minimum spend for this coupon is %s.', 'woocommerce' ), wc_price( $coupon->get_minimum_amount() ) ), 108 );
}
return $valid;
}
This code goes on function.php file of your active child theme (or theme). It should work.
Note: For everybody, remember to set in this function the coupon code in lowercase.

Change Add to cart button text to Added when product already in cart and product tag is buynow

I want to change the add to cart text to Added when product is already in cart and change the add to cart button text to Buy Now when product tag is buynow.
Here is my code:
/**
* Change the add to cart text on single product pages
*/
add_filter('woocommerce_product_single_add_to_cart_text', 'woo_custom_cart_button_text');
function woo_custom_cart_button_text() {
global $woocommerce;
foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if( get_the_ID() == $_product->id ) {
//return __('✓ Added', 'woocommerce');
return __('Added', 'woocommerce');
}
}
//return __('Add to cart', 'woocommerce');
if ( has_term( 'buynow', 'product_tag', $_product->id ) ) :
return __( 'Buy Now', 'woocommerce' );
else:
return __( 'Add to Cart', 'woocommerce' );
endif;
}
/**
* Change the add to cart text on product archives
*/
add_filter( 'woocommerce_product_add_to_cart_text', 'woo_archive_custom_cart_button_text' );
function woo_archive_custom_cart_button_text() {
global $woocommerce;
foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if( get_the_ID() == $_product->ID ) {
//return __('✓ Added', 'woocommerce');
return __('Added', 'woocommerce');
}
}
//return __('Add to cart', 'woocommerce');
if ( has_term( 'buynow', 'product_tag', $_product->ID ) ) :
return __( 'Buy Now', 'woocommerce' );
else:
return __( 'Add to Cart', 'woocommerce' );
endif;
}
My code works perfectly for single product page but not for product archive page.
Anyone have solution/suggestion for this please share.
Thanks in advance.
Use id instead of ID for the object $_product!
Try to use var_dump() to see what values are compared. You would have seen that $_product->ID was empty.
Finally Its working
Here is the code I put in woocommerce/loop/add-to-cart.php
global $product;
foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if( get_the_ID() == $_product->id ) {
$incart[] = $_product->id;
}
}
if (in_array($product->id, $incart, true)) {
$output = 'Added';
}elseif(in_array($product->id, $incart, true) && has_term( 'buynow', 'product_tag', $_product->id )){
$output = 'Added';
}elseif ( has_term( 'buynow', 'product_tag', $product->id ) ){
$output = 'Buy Now';
}else{
$output = 'Add to cart';
}

Categories