There are a few threads on here explaining how to get a product attribute in the cart or checkout. However, I just can't get it to work.
In the cart I can see the product attribute, but not in the checkout.
From what I've read, the checkout doesnt know about the product, so I need to load it. This would explain why Im not seeing it.
I've tried a lot of things, but I either don't get my shipping step to load in the cart, or it just doesn't display.
Any help would be great! Here is my code in a custom shipping module.
$cart = Mage::getSingleton('checkout/session');
//Order value by category
$gold = 0;
foreach ($cart->getQuote()->getAllItems() as $item) {
$itemPrice = $item->getPrice();
$qty = $item->getQty();
$metalType = Mage::getModel('catalog/product')->load($item->getProduct()->getId())->getAttributeText('metal');
if ($metalType == "Gold") {
//Apply some business logic
$gold = $itemPrice * $qty;
}
}
Magento get cart single item price incl. tax
Magento Product Attribute Get Value
In the afterLoad of the Mage_Sales_Model_Resource_Quote_Item_Collection object, a method is called to _assignProducts to each quote item. This method loads a product collection using the following code:
$productCollection = Mage::getModel('catalog/product')->getCollection()
->setStoreId($this->getStoreId())
->addIdFilter($this->_productIds)
->addAttributeToSelect(Mage::getSingleton('sales/quote_config')->getProductAttributes())
->addOptionsToResult()
->addStoreFilter()
->addUrlRewrite()
->addTierPriceData();
If you add the product attribute to the config.xml of your new module in the following way, it should be added as an attribute to be selected in the product collection.
<sales>
<quote>
<item>
<product_attributes>
<metal/>
</product_attributes>
</item>
</quote>
</sales>
Related
Hi for a Magento website i need to load a custom attribute in the shopping cart.
i use getmodel function to load the items. but i have no clue how i load the attribute. maybe i haven't configure the attribute right. i have enabled yes for enable on product listing. de attribute code is 'staffel_percentage'. it is just a regular string
also when i change the price per product it doesn't change the subtotal maybe this is because we already change the price for the product on the rest of the website?
maybe it is in the event? i use this event: controller_action_layout_render_before.
this is the code in observer i use for it
$cart = Mage::getModel('checkout/cart')->getQuote(); // Gets the collection of checkout
foreach ($cart->getAllItems() as $item) { // adds all items to $item and does the following code for each item
if ($item->getParentItem()) { // If items is part of a parent
$item = $item->getParentItem(); // Get parentItem;
}
//echo 'ID: '.$item->getProductId().'<br />';
$percentage = 80;// init first percentage
$quantity = $item->getQty(); //quantity
//$staffelstring = loadattribute//loads attribute
//gives the right percentage per quantity
//$staffelarray = explode(';', ^);
//foreach($staffelarray as $staffels){
//$stafel = explode(':', $staffels);
//if($quantity >= $stafel[0]){
//$percentage = $Stafel[1];
//}
//}
$currency = Mage::app()->getStore()->getCurrentCurrencyRate(); // Currencyrate that is used currently
$specialPrice = (($this->CalculatePrice($item) * $currency)* $percentage) / 100; //New prices we want to give the products
if ($specialPrice > 0) { // Check if price isnt lower then 0
$item->setCustomPrice($specialPrice); //Custom Price will have our new price
$item->setOriginalCustomPrice($specialPrice); //Original Custom price will have our new price, if there was a custom price before
$item->getProduct()->setIsSuperMode(true); //set custom prices against the quote item
}
}
You need to load the product right after your first if statement
$product = Mage::getModel('catalog/product')->load($item->getId()); // may be $item->getProductId() instead here
Then on the next line after that you can add some logging statements that will appear in var/log/system.log
Mage::log($product->getData()); // this will output all of the product data and attributes. You will see your custom attribute value here if it is set on this product.
If there is a value set for your product for your custom attribute then you can get it like this
$value = $product->getData('staffel_percentage');
As for the prices changing, not sure how you have the prices set up. You need to set a positive or negative number to add or subtract from the price in the fields found in the parent product configuration page in Catalog > Products > Your product > Associated Products.
See this image for what the section looks like.
I have an observer where I add a new quote item when the qty is more than one. Heres the code I use to create this quote item:
$quote_item = Mage::getModel('sales/quote_item');
$_product = Mage::getModel('catalog/product')->load($oldQuoteItem->getProduct()->getId());
$quote_item->setProduct($_product);
$quote_item->setQuote($quote);
$quote_item->setOriginalCustomPrice($oldQuoteItem->getProduct()->getPrice());
$quote_item->save();
It work's fine for simple products, but when I will duplicate a quote item with a configurable product, it will only take the parent product, and not the simple product that belongs to it, and therefore I get an error where the product is not on stock.
Anyone who got an idea, on how to duplicate the excact product to the new quote item ?
I have had success with the following for all product types.
$quote = Mage::getSingleton('checkout/session')->getQuote();
$oldQuoteItem = $quote->getItemById(ITEM_ID);
$product = Mage::getModel('catalog/product')
->setStoreId(Mage::app()->getStore()->getId())
->load($oldQuoteItem->getProductId());
$cart = Mage::getSingleton('checkout/cart');
$cart->addProduct($product, $oldQuoteItem->getBuyRequest());
$cart->save();
You should be able to then modify the item price.
Bear in mind if you want to do this for multiple products you must only save the cart once at the end after every $cart->addProduct()
I am trying to use the Magento reloadPrice() with jQuery to refresh the price. I have a configurable product with custom options. Without jQuery, the SELECT code for the option is :
<select id="select_281" class=" required-entry product-custom-option" title="" name="options[281]" onchange="opConfig.reloadPrice()">
<option value="0"></option>
<option rel="1" price="0" value="275"></option>
<option rel="2" price="0" value="276"></option>
</select>
With jQuery I remove the Prototype onchange code and try to calculate the price for my option (say $50) :
jQuery('#select_281').removeAttr('onchange').change(function(){
//Price of the option to add to a basic price of the conf product
price = 50;
optionsPrice.changePrice('opConfig', price);
optionsPrice.reload();
});
Price of the configurable product: $150.
Add an option (SELECT): we add $50.
The new price $200 is displayed in the product page, But not in the cart page : the cart page displays just $150 which is not correct.
Someone can help?
Best regards,
COM.
The reloadPrice() cant change any price serverside.
So we solved this issue by using 2 observers : checkout_cart_product_add_after observer to change the price the first time the product is added to the cart, and checkout_cart_update_items_after observer to change the price for each item in the cart (when user click the "Modify cart" button on cart page).
The code here tested for configurable products with 2 custom options numberOfColors and engravingType. For each couple numberOfColors/engravingType we have tierprices stored in special MySQL table, we may change price with a custom price. Each simple product has its tierPrices.
<code>//checkout_cart_product_add_after observer
public function modifyPrice(Varien_Event_Observer $observer)
{
$item = $observer->getQuoteItem();
$item = ( $item->getParentItem() ? $item->getParentItem() : $item );
$productType = $product->getTypeID();
$price = 100;//Unit price of product without engraving, 100 for example
//Unit price with engraving, depending of 2 custom options of configurable product
if($productType == 'configurable'){
//get custom options of config here
.
.
$engravingPrice = 1.2;//Get unit price with engraving from a special MySQL table
$finalUnitPrice = $price + $engravingPrice;//Final custom price
//Modify the price
$item->setCustomPrice($finalUnitPrice);
$item->setOriginalCustomPrice($finalUnitPrice);
$item->getProduct()->setIsSuperMode(true);
}
}
//checkout_cart_update_items_after observer
public function modifyCartItems(Varien_Event_Observer $observer)
{
foreach ($observer->getCart()->getQuote()->getAllVisibleItems() as $item ) {
if ($item->getParentItem()) {$item = $item->getParentItem();}
$productType = $product->getTypeID();
$productType = $product->getTypeID();
$price = 100;//Unit price of product without engraving
//Unit price with engraving, depending of 2 custom options of configurable product
if($productType == 'configurable'){
.
.
$engravingPrice = 1.2;//Get unit price with engraving from a special MySQL table
$finalUnitPrice = $price + $engravingPrice;//Final custom price
//Modify the price for the item
$item->setCustomPrice($finalUnitPrice);
$item->setOriginalCustomPrice($finalUnitPrice);
$item->getProduct()->setIsSuperMode(true);
}
}
}</code>
But.....one problem remains : on the cart page, when user clicks the link "Edit" to edit the product in product page so he can change quantity, ...and click the "Update cart" button, this update button does not read the checkout_cart_product_add_after to refresh price.
Dont't know how to force this "Update cart" action to process the code in checkout_cart_product_add_after observer? Is this code executed just the first time the product is added to the cart?
Thanks.
COM
I am currently working on the development of a management module Cart on Magento 1.9
I'm stuck on adding a product to my cart (I tried many different things) and that's why I solicits your help.
My module extends the rest API of magento and I have already managed update to my cart (quantity of products) but now I'll wish to add a new product via the POST method.
Of course I'm logged as customer. I defined the creation privileges for this role. (I can do the update without problems)
Here is my code :
protected function _create(array $data){
$store = $this->_getStore();
Mage::app()->setCurrentStore($store->getId());
$cart = Mage::getModel('checkout/cart');
$cart->init();
$productCollection = Mage::getModel('catalog/product')->load(4);
// Add product to cart
$cart->addProduct($productCollection,
array(
'product_id' => $productCollection->getId(),
'qty' => '1'
)
);
// Save cart
$cart->save();
}
In this simple example, I try to add the product id 4 in quantity 1.
My problem is that I have no error in the log, and everything seems to be past. But when I get my cart, there is no product to add...
in return I have a code 200 OK
Do you have any suggestions to help me?
Thanks a lot for your help
regards
I finally found the solution after traveling all internet;)
In fact when you want to reach the cart before checkout, magento uses the definition "Quote" ... Not easy to understand for a beginner on Magento....
So in order to facilitate research of those who are like me had troubles, here is my code to add a new product in the cart (before checkout) :
//$data['entity_id'] = The id of the product you want to add to the cart
//$data['qty'] = The quantity you want to specify
protected function _create(array $data)
{
$store = $this->_getStore();
Mage::app()->setCurrentStore($store->getId());
// Get Customer's ID
$customerID = $this->getApiUser()->getUserId();
// Load quote by Customer
$quote = Mage::getModel('sales/quote')
->loadByCustomer($customerID);
$product = Mage::getModel('catalog/product')
// set the current store ID
->setStoreId(Mage::app()->getStore()->getId())
// load the product object
->load($data['entity_id']);
// Add Product to Quote
$quote->addProduct($product,$data['qty']);
try {
// Calculate the new Cart total and Save Quote
$quote->collectTotals()->save();
} catch (Mage_Core_Exception $e) {
$this->_error($e->getMessage(),Mage_Api2_Model_Server::HTTP_INTERNAL_ERROR);
}
}
I hope this can help someone
Regards
Carniflex
I want to add a product to cart programmatically. Also, I want to change the product price when added to cart.
Suppose, my product's price is $100. I wanted to change it to $90 when added to cart.
I added product to cart. However, I am unable to change the product price.
Is it possible?
Here is the code to add product to cart:-
$cart = Mage::getSingleton('checkout/cart');
try {
$cart->addProduct($product, array('qty' => 1));
$cart->save();
}
catch (Exception $ex) {
echo $ex->getMessage();
}
After digging a bit into Magento's core code, I found that you need to use $item->getProduct()->setIsSuperMode(true) in order to make $item->setCustomPrice() and $item->setOriginalPrice() work.
Here is some sample code you can use within an Observer that listens for the checkout_cart_product_add_after or checkout_cart_update_items_after events. The code is logically the same except checkout_cart_product_add_after is called for only one item and checkout_cart_update_items_after is called for all items in the cart. This code is separated/duplicated into 2 methods only as an example.
Event: checkout_cart_product_add_after
/**
* #param Varien_Event_Observer $observer
*/
public function applyDiscount(Varien_Event_Observer $observer)
{
/* #var $item Mage_Sales_Model_Quote_Item */
$item = $observer->getQuoteItem();
if ($item->getParentItem()) {
$item = $item->getParentItem();
}
// Discounted 25% off
$percentDiscount = 0.25;
// This makes sure the discount isn't applied over and over when refreshing
$specialPrice = $item->getOriginalPrice() - ($item->getOriginalPrice() * $percentDiscount);
// Make sure we don't have a negative
if ($specialPrice > 0) {
$item->setCustomPrice($specialPrice);
$item->setOriginalCustomPrice($specialPrice);
$item->getProduct()->setIsSuperMode(true);
}
}
Event: checkout_cart_update_items_after
/**
* #param Varien_Event_Observer $observer
*/
public function applyDiscounts(Varien_Event_Observer $observer)
{
foreach ($observer->getCart()->getQuote()->getAllVisibleItems() as $item /* #var $item Mage_Sales_Model_Quote_Item */) {
if ($item->getParentItem()) {
$item = $item->getParentItem();
}
// Discounted 25% off
$percentDiscount = 0.25;
// This makes sure the discount isn't applied over and over when refreshing
$specialPrice = $item->getOriginalPrice() - ($item->getOriginalPrice() * $percentDiscount);
// Make sure we don't have a negative
if ($specialPrice > 0) {
$item->setCustomPrice($specialPrice);
$item->setOriginalCustomPrice($specialPrice);
$item->getProduct()->setIsSuperMode(true);
}
}
}
Magento have changed the way the prices are calculated in the cart which makes it very difficult to do this in v1.4 onwards. If you do set the price using an Observer or other device, it will almost certainly be overwritten back to the catalog price.
Effectively, you need to use Shopping Cart rules to implement this.
It is possible to set a customer specific price of a quote item. Hence, something like this should do it:
$quoteItem = $quote->addProduct($product, $qty);
$quoteItem->setCustomPrice($price);
// we need this since Magento 1.4
$quoteItem->setOriginalCustomPrice($price);
$quote->save();
Hope this helps...
Jonathan's answer is likely the best for most situations. But some customers might not like how shopping cart discounts are displayed in the cart. I recently did a project (with Magento 1.3.3) where the customer didn't like how the each line item still showed the full price as well as the subtotal, with a Discount line below the subtotal - he wanted to see the price of each item discounted, and the subtotal show the discounted price as well. He really didn't like having the Discount line after the Subtotal line.
Anyway, if you find yourself in the same boat, one approach is to override the getCalculationPrice() and getBaseCalculationPrice() methods in Mage_Sales_Model_Quote_Address_Item and Mage_Sales_Model_Quote_Item. I know that it isn't always pretty to override, much better to use events, but in this case I couldn't get events to work seamlessly on both the frontend and backend. Not sure if this approach will work in Magento 1.4+.
If I have to share my solution that I made on the base of Simon then I have managed to rewrite model class save function of quote.
public function save()
{
$this->getQuote()->getBillingAddress();
$this->getQuote()->getShippingAddress()->setCollectShippingRates(true);
$this->getQuote()->collectTotals();
//$this->getQuote()->save();
foreach($this->getQuote()->getAllItems() as $item) {
$productId = $item->getProductId();
$product = Mage::getModel('catalog/product')->load($productId);
if($product->getAttributeText('is_dummy') == 'Yes') {
$price = 2;
$item->setCustomPrice($price);
// we need this since Magento 1.4
$item->setOriginalCustomPrice($price);
}
}
$this->getQuote()->save();
$this->getCheckoutSession()->setQuoteId($this->getQuote()->getId());
/**
* Cart save usually called after chenges with cart items.
*/
Mage::dispatchEvent('checkout_cart_save_after', array('cart'=>$this));
return $this;
}
I had the same issue and i am not a developer. What i did was added a new price attribute in magento backend called "site price". On the product page this showed the higher price $100. the actual price of the item was $90. so when the shopper adds it to cart they will see the actual price of the item, but on the product page they see the custom attribute price of $100
if all your prices on the product page are a set % higher then the real price just multiply your product price by the 1+percent. So if you want to add 10% to all your prices do price*1.1
This will display your price as 10% higher but when the shopper adds to cart they will see the real price.