Reputation: 939
Using this code to reduce the stock from inventory by Attribute Value. It works to reduce the stock, but when you have like 100 g in stock and the customer buys 120 g. It doesn't show Out of Stock.
So the following code was created:
<?php
add_filter( 'woocommerce_order_item_quantity', 'filter_order_item_quantity', 10, 3 );
function filter_order_item_quantity( $quantity, $order, $item )
{
$product = $item->get_product();
$stock_quantity = $product->get_stock_quantity();
$term_name = $product->get_attribute('pa_weight');
// The 'pa_size' attribute value is "15 grams" And we keep only the numbers
$quantity_grams = preg_replace('/[^0-9.]+/', '', $term_name);
// Calculated new quantity
if( is_numeric ( $quantity_grams ) && $quantity_grams != 0 )
$quantity *= $quantity_grams;
if($quantity > $stock_quantity) {
return $quantity;
} else {
echo '<p>Out of Stock</p>';
}
}
However, it isn't working...
Is there a way to check the stock from $quantity?
if($quantity > $stock_quantity) {
return $quantity;
} else {
echo '<p>Out of Stock</p>';
}
EDIT:
Tried to reduce the stock with a hook to wc_reduce_stock_levels
, without success
add_filter( 'wc_reduce_stock_levels', 'filter_reduce_stock_levels', 5, 1);
function filter_reduce_stock_levels( $order_id ) {
if ( is_a( $order_id, 'WC_Order' ) ) {
$order = $order_id;
$order_id = $order->get_id();
} else {
$order = wc_get_order( $order_id );
}
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) && $order && apply_filters( 'woocommerce_can_reduce_order_stock', true, $order ) && sizeof( $order->get_items() ) > 0 ) {
foreach ( $order->get_items() as $item ) {
if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) && $product->managing_stock() ) {
$term_name = $product->get_attribute('pa_weight');
$qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
$item_name = $product->get_formatted_name();
$new_stock = wc_update_product_stock( $product, $qty, 'decrease' );
$quantity_grams = preg_replace('/[^0-9.]+/', '', $term_name);
$qty *= $quantity_grams;
if ( ! is_wp_error( $new_stock ) ) {
/** translators: 1: item name 2: old stock quantity 3: new stock quantity */
$order->add_order_note( sprintf( __( '%1$s stock reduced from %2$s to %3$s.', 'woocommerce' ), $item_name, $new_stock + $qty, $new_stock ) );
// Get the latest product data.
$product = wc_get_product( $product->get_id() );
if ( '' !== get_option( 'woocommerce_notify_no_stock_amount' ) && $new_stock <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {
do_action( 'woocommerce_no_stock', $product );
} elseif ( '' !== get_option( 'woocommerce_notify_low_stock_amount' ) && $new_stock <= get_option( 'woocommerce_notify_low_stock_amount' ) ) {
do_action( 'woocommerce_low_stock', $product );
}
if ( $new_stock < 0 ) {
do_action( 'woocommerce_product_on_backorder', array( 'product' => $product, 'order_id' => $order_id, 'quantity' => $qty ) );
}
}
}
}
// ensure stock is marked as "reduced" in case payment complete or other stock actions are called
$order->get_data_store()->set_stock_reduced( $order_id, true );
do_action( 'woocommerce_reduce_order_stock', $order );
}
}
Upvotes: 1
Views: 1103
Reputation: 3799
Remove all your old codes and add these to your theme's 'functions.php'.
// reduce stock based on 'pa_weight' attribute
add_filter( 'woocommerce_order_item_quantity', 'filter_order_item_quantity', 10, 3 );
function filter_order_item_quantity( $quantity, $order, $item )
{
$product = $item->get_product();
$term_name = $product->get_attribute('pa_weight');
// 'pa_weight' attribute value is "15 grams" - keep only the numbers
$quantity_grams = preg_replace('/[^0-9.]+/', '', $term_name);
// new quantity
if( is_numeric ( $quantity_grams ) && $quantity_grams != 0 )
$quantity *= $quantity_grams;
return $quantity;
}
// check out of stock using 'pa_weight' attribute
add_filter( 'woocommerce_add_to_cart_validation', 'woocommerce_validate_attribute_weight' );
function woocommerce_validate_attribute_weight()
{
// get product id
if (isset($_REQUEST["add-to-cart"])) {
$productid = (int)$_REQUEST["add-to-cart"];
} else {
$productid = null;
}
// get quantity
if (isset($_REQUEST["quantity"])) {
$quantity = (int)$_REQUEST["quantity"];
} else {
$quantity = 1;
}
// get weight of selected attribute
if (isset($_REQUEST["attribute_pa_weight"])) {
$weight = preg_replace('/[^0-9.]+/', '', $_REQUEST["attribute_pa_weight"]);
} else {
$weight = null;
}
// comparing stock
if($productid && $weight)
{
$product = wc_get_product($productid);
$productstock = (int)$product->get_stock_quantity();
if(($weight * $quantity) > $productstock)
{
wc_add_notice( sprintf( 'You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', $product->get_title(), $productstock ), 'error' );
return;
}
}
return true;
}
The first function almost same as your's and you cannot show out of stock message using the woocommerce_order_item_quantity
since it will execute only after successful order confirmation.
You need to validate the new stock while adding your product to the cart which can be achieved by using the second function (utilizing woocommerce_add_to_cart_validation
).
Upvotes: 1
Reputation: 761
I never used woo commerce but I see that you are trying to get number from e.g. 15 grams
. I am not sure but most probably you should do same thing for $stock_quantity
as well. The final code should be something like this. And I also noticed that you are checking that if requested quantity is grater than stock quantity then return it which is not logical. It should be vice versus. I mean requested quantity should be less or equal to stock quantity.
<?php
add_filter( 'woocommerce_order_item_quantity', 'filter_order_item_quantity', 10, 3 );
function filter_order_item_quantity( $quantity, $order, $item )
{
$product = $item->get_product();
$stock_quantity = $product->get_stock_quantity();
$term_name = $product->get_attribute('pa_weight');
// The 'pa_size' attribute value is "15 grams" And we keep only the numbers
$quantity_grams = preg_replace('/[^0-9.]+/', '', $term_name);
$stock_quantity = (int)preg_replace('/[^0-9.]+/', '', $stock_quantity);
// Calculated new quantity
if( is_numeric ( $quantity_grams ) && $quantity_grams != 0 )
$quantity *= $quantity_grams;
if($quantity <= $stock_quantity) {
return $quantity;
} else {
return '<p>Out of Stock</p>';
}
}
Upvotes: 0