I am creating a magento extension. In which I want to update the item quantity in cart programmatically. I am using the following code to display the items in cart.
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();
foreach ($cartItems as $item) {
//Do something
}
What i want is to update the quantity on cart for a specific product. I know it can be done like this
$pid=15;
$quote = Mage::getSingleton('checkout/session')->getQuote();
$cartItems = $quote->getAllVisibleItems();
foreach ($cartItems as $item) {
if($pid==$item->getId())
$item->setQty($qty);
}
But I don't like this method as it would go through each and every product to update the quantity of a single product. I wonder if there is a way to update the quantity in one line i:e without using for loop.
You have the product_id, not the item_id right ?
If it's the case it's impossible to get the product id without performing the whole items.
Look at Mage_Sales_Model_Quote::getItemByProduct($product); you'll see it performs the whole catalog.
Basically I'll do it like this :
//get Product
$product = Mage::getModel('catalog/product')->load($pid);
//get Item
$item = $quote->getItemByProduct($product);
$quote->getCart()->updateItem(array($item->getId()=>array('qty'=>$qty)));
$quote->getCart()->save();
You should optimise this with some quick tricks :
$quote->hasProductId($pid) to check if product is in the cart
and
($qty!=$item->getQty())
to check if quantity is not already good...
Please note that it is untested code, and some kind of reflexions to help you find the solution, I didn't do the job for you.
Kind Regards,
I am sure it will work. Try this. It's save's my time.
public function updateCartAction(){
$item_id = $this->getRequest()->getParam('item_id');
$qty = $this->getRequest()->getParam('qty');
$quote = Mage::getSingleton('checkout/session')->getQuote();
$quote->updateItem($item_id, array( 'qty' => $qty));
$quote->save();
echo "Sssssss";
}
another solution
$quote = Mage::getModel('sales/quote')->setStoreId($storeId)->load($cartid);
$cartItems = $quote->getAllItems();
foreach ($cartItems as $item) {
if($cartiemid==$item->getId()){
$item->setQty($qty);
$item->save(); // you need to save the item after qty update
}
}
$quote->save();
Related
I want only allow one purchase for each product, so I want to disable the add to cart for the user who already purchased that product.
I've been reading and I think I should use the woocommerce_is_purchasable hook
but I have no idea how to do it, I would appreciate the help, thank you.
Assuming you're talking about simple products*, you can do this by hooking into is_purchasable.
For the logged in customer, the following code gets the product ID's of all past orders. If the current product ID is in that collection, it returns false for is_purchasable.
Add it to the functions.php file of your child theme.
add_filter('woocommerce_is_purchasable', 'preventPurchaseIfAlreadyOrdered', 10, 2);
function preventPurchaseIfAlreadyOrdered($is_purchasable, $product) {
$productId = $product->get_id();
$orderedItemIdArray = getOrdersItemIdsForCurrentUser();
$is_purchasable = !in_array($productId, $orderedItemIdArray);
return $is_purchasable;
}
function getOrdersItemIdsForCurrentUser() {
$orders = wc_get_orders(['author' => get_current_user_id()]);
if (empty($orders)) return;
$orderedItemIdArray = [];
foreach ($orders as $order) {
$items = $order->get_items();
foreach ($items as $item) {
$orderedItemIdArray[] = $item->get_product_id();
}
}
return $orderedItemIdArray;
}
The code has been tested and works.
* for variable products, the selected variation can change without reloading the page, i.e. via Ajax. That process is more involved (but also possible).
I am trying to change the quantity, subtotal and total of a line item in woocommerce, but my code seems to not change anything but the end total... why is that?? (there is only 1 line item for any order I want to change)
here is my code to change a line item details;
$ordernum = 12345; //what I want
$qnty = 30; //or whatever
$subtotal = 10;
$total = 300; //for show
$order = wc_get_order($ordernum);
foreach( $order->get_items() as $item_id => $item ){
$item->set_quantity($qnty);
$item->set_subtotal($subtotal);
$item->set_total($total);
$item->save();
}
$order->set_total($total);
$order->save();
EDIT: it seems to take forever for the changes to take effect on the admin panel... what would be the case since this is done programmatically... or is it stored?
I don't know woocommerce but think that you should call $item->save() on item in each loop run ofc.
I need to remove some products from cart after the customer press the "Place order" button. I can remove the products with a custom event and observer and update the cart products, but i cant update the cart total.
In the observer i try to update the price with:
$granTotal = $cart->getGrandTotal() - $cart->getShippingAmount();
$cart->setGrandTotal($GranTotal - $sum)->save();
$baseGranTotal = $cart->getBaseGrandTotal() - $cart->getShippingAmount();
$cart->setBaseGrandTotal($baseGranTotal - $sum)->save();
$cart->setTotalsCollectedFlag(false)->collectTotals();
$cart->save();
But the total of the cart don't change. I find that the total is stored in the cart address too and used to set the cart total in Mage_Sales_Model_Quote collectTotals() function.
Here:
$this->setSubtotal((float) $this->getSubtotal() + $address->getSubtotal());
$this->setBaseSubtotal((float) $this->getBaseSubtotal() + $address->getBaseSubtotal());
Then i tried to change the address total before calling the collectTotals(), but the cart total still don't change.
My custom event is triggered at the beginning in Mage_Checkout_Model_Type_Onepage saveOrder() function.
I am running out of ideas of how to update the total of the cart.
My observer looks like this:
public function changeCart(){
$cart = Mage::getSingleton('checkout/session')->getQuote();
$data = array();
$inquiry = array();
$sum = 0;
//remove out of stock items to save them in custom model
foreach ($cart->getAllItems() as $item) {
if($item->getProduct()->getData('is_in_stock') == 0){
$cart->removeItem($item->getItemId())->save();
$inquiry[] = $item->getProduct();
$data['qty'][$item->getProduct()->getId()] = $item->getData('qty');
$sum += $item->getProduct()->getFinalPrice();
$dobavljivost = $item->getProduct()->getResource()->getAttributeRawValue($item->getProduct()->getId(), 'dobavljivost', Mage::app()->getStore());
Mage::getSingleton('core/session')->setDobavljivost($dobavljivost);
}
}
foreach($cart->getAllAddresses() as $a){
$a->setGrandTotal(0);;
$a->setBaseGrandTotal(0);
$a->setData('subtotal', 0);
$a->setData('base_subtotal', 0);
}
$granTotal = $cart->getGrandTotal() - $cart->getShippingAmount();
$cart->setGrandTotal($GranTotal - $sum)->save();
$baseGranTotal = $cart->getBaseGrandTotal() - $cart->getShippingAmount();
$cart->setBaseGrandTotal($baseGranTotal - $sum)->save();
$cart->setTotalsCollectedFlag(false)->collectTotals();
$cart->save();
}
Thank you for any help!
For recomputing totals of the cart you can try do this
$cart = Mage::getSingleton('checkout/session')->getQuote();
foreach ($cart->getAllAddresses() as $address)
{
$address->unsetData('cached_items_nonnominal');
$address->unsetData('cached_items_nominal');
}
$cart->setTotalsCollectedFlag(false);
$cart->collectTotals();
I want to get the remain quantity of a given product. I'm going to create a report in admin panel which highlights the remaining quantity and re-order level quantity against each product. I was able to get the re-order level quantity by inventory details. And I want to get remain quantity for a given product. Please any suggestions?
Try
<?php
$num= Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
echo "Remaining products: ".$num;
?>
If you are looking for the remaining quantity for products in the cart, you need to take into account configurable vs simple products:
<?php
$quote = Mage::getModel('checkout/cart')->getQuote();
$items = $quote->getAllVisibleItems();
foreach ($items as $item) {
$cart_product = $item->getProduct();
if ($option = $item->getOptionByCode('simple_product')) {
$cart_simple_product = $option->getProduct();
} else {
$cart_simple_product = $this->getProduct();
}
$stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($cart_simple_product);
$max_available_quantity = (int)$stock->getQty();
}
?>
I'm running into a problem with getting attribute values for products that have been placed in a users cart.
I have the following code:
umask(0);
Mage::app();
Mage::getSingleton('core/session', array('name'=>'frontend'));
$session = Mage::getSingleton('checkout/session');
$cart = Mage::helper('checkout/cart')->getCart()->getItemsCount();
foreach ($session->getQuote()->getAllItems() as $item) {
$_product = Mage::getModel('catalog/product')->load($item->getId());
$attributeValue = $_product->getAttributeText('availability');
echo $attributeValue;
}
And it works fine for all products in the cart except the very last one. For example, I'm trying to get the value of an "availability" attribute I've created that can have only 1 of the following values "Backorder", "Preorder", "Out of Stock". If I have 3 items in my cart I can get the correct values for the first 2, however for the last item it just displays "No".
I have double checked each item to make sure all attributes are set correctly and it happens with any number of items in the cart.
Hopefully it's just a stupid mistake on my part.
Any help would be appreciated.
Thanks.
SOLVED:
Changing:
$_product = Mage::getModel('catalog/product')->load($item->getId());
to
$_product = Mage::getModel('catalog/product')->load($item->getProductId());
Fixes the issue.
The problem is in that line:
$_product = Mage::getModel('catalog/product')->load($item->getId());
With $item->getId() you are getting ID of Mage_Sales_Model_Quote_Item and not Mage_Catalog_Model_Product. You have to use $item->getProductId() instead to get ID of actual product associated with current quote item.