With a simple product I can do this:
$quote = Mage::getSingleton('checkout/session')->getQuote();
$item = $quote->getItemById($params['item']); // $params['item'] contains item id
$product = $item->getProduct();
$stockQty = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($product)->getQty();
However, if the item is a configured product, it tries to get the stock of its parent configurable product, which in most cases has an inventory of zero.
How can I get the stock quantity of a configured product, preferably without looping through its configurable parent's child products?
You can set a variable that determines the stock status depending on the stock status of the children of the configurable product:
$inStock = true;
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cart = Mage::getModel('checkout/cart')->getQuote();
$item = $quote->getItemById($params['item']); // $params['item'] contains item id
$_product = $item->getProduct();
$configuredProduct = Mage::getModel('catalog/product_type_configurable')->setProduct($_product);
$children = $configuredProduct->getUsedProductCollection()->addAttributeToSelect("*")->addFilterByRequiredOptions();
foreach($children as $simpleProduct) {
foreach ($cart->getAllItems() as $item) {
if ($item->getProduct()->getId() != $simpleProduct->getId()) continue;
$stockQty = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($simpleProduct)->getQty();
if ($stockQty <= 0) {
$inStock = false;
break;
}
}
}
Related
I am wondering if I can add some sort of code to my woocommerce store to set accumulated maximum purchase quantity from a category for certain user role.
For example,
3 user roles: A, B, C
3 product categories: 1,2,3
I want to limit roles A to only purchase maximum of 2 products from Cat 1 throughout the lifetime of their membership, while still able to purchase any amount of product from Cat2,3
Meanwhile for roles B and C, the logic is pretty much same but the maximum accumulated quantity will be different.
Is that possible to write some sort of code in function php?
You can use hook woocommerce_add_to_cart_validation.
For example:
add_filter('woocommerce_add_to_cart_validation', function($valid, $product_id, $quantity) {
$cat_id = CAT_ID; // CAT_ID ----YOUR category id
$your_quantity = YOUR_QUANTITY;
$user_role = YOUR_USER_ROLE;
$user = wp_get_current_user();
$user_roles = $user->roles;
if(!in_array($user_role, $user_roles)) {
return $valid;
}
$product = wc_get_product($product_id);
$current_product_categories = $product->get_category_ids();
//check if quantity is bigger than allowed
if(in_array($cat_id, $current_product_categories) && $quantity > $your_quantity) {
return false;
}
//Counter for products in cart and orders.
$counter = 0;
//check whole cart
$cart_items = WC()->cart->get_cart();
foreach($cart_items as $cart_key => $cart_data) {
$product = wc_get_product($cart_data['product_id']);
$cart_product_categories = $product->get_category_ids();
if(in_array($cat_id, $cart_product_categories)) {
$counter = $counter + 1 * $cart_data['quantity'];
}
}
if($counter > $your_quantity) {
return false;
}
//All user's orders
$user_orders = wc_get_orders(array(
'customer' => get_current_user_id( )
));
if($user_orders->total > 0) {
foreach($user_orders as $order) {
$products = $order->get_items('line_item');
foreach ($products as $product) {
$product_categories = $product->get_category_ids();
if(in_array($cat_id, $product_categories)) {
$counter++;
}
}
}
}
if($counter > $your_quantity) {
return false;
}
return $valid;
}, 10, 3);
You can also place wc_add_notice() when you return false;
i'm a bit stuck for this.. i'm trying to remove a condition whenever the user adds a specific product, in this case a box of wines
So when i add a bottle of wine there's a minium amount condition so you have to add 3, but when you add a box the condition must be removed
add_action('woocommerce_after_cart_contents', 'box_special_function', 1, 1);
function box_special_function()
{
// getting cart items
$cart = WC()->cart->get_cart();
$terms = [];
// Getting categories of products in the cart
foreach ($cart as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$terms[] = get_the_terms( $product->get_id(), 'product_cat' );
}
// Cycling categories to find if there is a box inside of the cart
foreach($terms as $term => $item){
foreach($item as $key){
if($key->name == "BOX"){
// The only thing i did is to remove notices (which doesn't even work .-.)
$notices = WC()->session->get('wc_notices', array());
foreach($notices['error']){
wc_clear_notices();
}
}
}
}
}
I can't even force to checkout so i'm stuck with this.. can somebody clear my mind?
You can update your minimum product add to cart functionality, and remove validation for your specific products like this:
add_filter( 'woocommerce_quantity_input_args', 'custom_woocommerce_quantity_changes', 10, 2 );
function custom_woocommerce_quantity_changes( $args, $product ) {
$product_id = $product->get_id();
$product_title = $product->get_title();
//echo "<pre>"; print_r($product_title); echo "</pre>";
if($product_id == 1002 || $product_title == 'BOX'){
$args['input_value'] = 1;
$args['min_value'] = 1;
$args['max_value'] = 30;
$args['step'] = 1;
}else{
$args['input_value'] = 3; // Start from this value (default = 1)
$args['max_value'] = 30; // Max quantity (default = -1)
$args['min_value'] = 3; // Min quantity (default = 0)
$args['step'] = 1; // Increment/decrement by this value (default = 1)
}
return $args;
}
print your specific product id or product name and use same name or id in your if condition :
if($product_id == 1002 || $product_title == 'BOX')
For rest of product set min, max and input product validation from "else" parts.
I have session to add product cart.
$getProductID = mysqli_real_escape_string($con, $_POST['productID']);
$getQuantity = mysqli_real_escape_string($con, $_POST['quantity']);
foreach($_POST as $key => $value)
{
$new_product[$key] = filter_var($value, FILTER_SANITIZE_STRING);
}
$qProduct = mysqli_query($con, "SELECT * FROM tb_product WHERE productid = '" . $getProductID . "'");
$dProduct = mysqli_fetch_array($qProduct);
$product_id = $dProduct['productid'];
$product_name = $dProduct['product_name'];
$product_price = $dProduct['product_price'];
$new_product["productid"] = $product_id;
$new_product["product_name"] = $product_name;
$new_product["product_price"] = $product_price;
$new_product["quantity"] = $getQuantity;
if(isset($_SESSION["products"]))
{
if(isset($_SESSION["products"][$new_product['productid']]))
{
unset($_SESSION["products"][$new_product['productid']]);
}
}
$_SESSION["products"][$new_product['productid']] = $new_product;
$total_items = count($_SESSION["products"]);
foreach($_SESSION["products"] as $product)
{
$product_quantity = $product["quantity"];
}
die(json_encode(array('items'=>$product_quantity)));
Then now I want to get session of product quantity
foreach($_SESSION["products"] as $product)
{
echo $product_quantity = $product["quantity"];
}
I can get the quantity as well, until I try to add another product cart it's not sum the quantity.
Example, on Product1 I add to cart 5pcs (I can see the quantity is 5)
and then I add Product2 to cart 3pc (It show me 53 that should be 8).
My question, how to sum the quantity even Product ID is different?
Change your loop as below, Sum inside loop and move echo outside of loop.
$product_quantity = 0;
foreach($_SESSION["products"] as $product)
{
$product_quantity += $product["quantity"];
}
echo $product_quantity;
I think because your coding have something wrong
//Incorrect
foreach($_SESSION["products"] as $product)
{
echo $product_quantity = $product["quantity"];
}
//first loop echo-ed 5
//second loop echo-ed 3
//so it show 53
//Correct
$product_quantity = 0;
foreach($_SESSION["products"] as $product)
{
$product_quantity += $product["quantity"];
}
echo $product_quantity;
I would like to check item gonna be add to cart is already in cart and belong to which category, if that category have over 5 products then throw an exception message:
function check_product_in_cart() {
//Check to see if user has product in cart
global $woocommerce;
// start of the loop that fetches the cart items
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
// second level loop search, in case some items have several categories
$cat_ids = array();
foreach ($terms as $term) {
$cat_ids[] = $term->term_id;
}
if(in_array(434, (array)$cat_ids) || in_array(435, (array)$cat_ids)) {
//category is in cart!
$product_in_cart = true;
//count the category?
$count = 1;
while($product_in_cart === true) {
$count +=1;
}
}
}
return $product_in_cart;
return $count;
}
then echo out the error message can not add to cart. what is the best way to count product in cart per category?. Basically, I want to limit item add to cart per category. Thanks guys
I'm writing a plugin and cannot get the correct variation title
In Woocommerce the variation i use is called "unfolded laminated". but when i try to get the title of a variation i get: "Variation #781 of Chart"
This is the code is use:
foreach ($order->get_items() as $item) {
$product_variation_id = $item['variation_id'];
if ($product_variation_id)
{
$product = new WC_Product($product_variation_id);
$productname = get_item_variations($product_variation_id);
}
else
{
$product = new WC_Product($item['product_id']);
$productname = get_the_title($item['product_id']);
}
}
How do i get the correct title?
I was actually looking this up trying to figure it out and here's my solution because the variation title was returning a slug.
Tested on WC 2.4.13
$variation = new WC_Product_Variation($variation_id);
$title_slug = current($variation->get_variation_attributes());
$results = $wpdb->get_results("SELECT * FROM wp_terms WHERE slug = '{$title_slug}'", ARRAY_A);
$variation_title = $results[0]['name'];
I stumbled across this just now looking for a 'quick' fix. Since no-one has posted an answer I thought I would.
I just used WordPress get_post_meta to fetch attribute_options. This is where all the option titles are stored (variation titles are product options).
$product_options = get_post_meta($item['variation_id'], 'attribute_options');
Will return an array
[attribute_options] => Array
(
[0] => Some Variation Title
)
Here is a solution for this problem which is tested with WooCommerce 3.2.6
//Loop through each item from the cart
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
//get the current product ID
$product_id = $cart_item['product_id'];
//first - check if product has variations
if(isset($cart_item['variation']) && count($cart_item['variation']) > 0 ){
//get the WooCommerce Product object by product ID
$current_product = new WC_Product_Variable($product_id);
//get the variations of this product
$variations = $current_product->get_available_variations();
//Loop through each variation to get its title
foreach($variations as $index => $data){
get_the_title($data['variation_id']);
}
}
}
In this function to return the title of the input variation, you can change the delimiter ', ' to a space or whatever is needed.
function get_variation_title($variation) {
$str_name = '';
$arr_attributes = $variation -> get_variation_attributes(FALSE);
if (is_array($arr_attributes)) {
foreach($arr_attributes as $attribute_slug=> $variation_slug) {
$term = get_term_by('slug', $variation_slug, $attribute_slug);
if (isset($term)) {
if (strlen($str_name) > 0) $str_name.= ', ';
$str_name.= $term -> name;
}
}
}
return $str_name;
}