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.
Related
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>
I use the code below for changing the price into the Magento cart dynamic.
class Test_Pricecalc_Model_Observer
{
public function modifyPrice(Varien_Event_Observer $obs)
{
// Get the quote item
$item = $obs->getQuoteItem();
// Ensure we have the parent item, if it has one
$item = ( $item->getParentItem() ? $item->getParentItem() : $item );
// Load the custom price
$price = $this->_getPriceByItem($item);
// Set the custom price
$item->setCustomPrice($price);
$item->setOriginalCustomPrice($price);
// Enable super mode on the product.
$item->getProduct()->setIsSuperMode(true);
}
protected function _getPriceByItem(Mage_Sales_Model_Quote_Item $item)
{
$price = $price + 10;
return $price;
}
protected function _getRequest()
{
return Mage::app()->getRequest();
}
}
Does someone now how to get the custom price from the product detail page after choosing the product options there? I want to use that price as basis price fur my further calculation.
You can create a hidden input field in product detail page with value equal to your custom price.
and can get that field in your observer like:
$new_price = Mage::app()->getRequest()->getPost('custom_price');
where 'custom_price' is the name of your hidden field and $new_price in oberserver is your custom price.
here is an example, which we used to render our product price during "add to cart":-
class Tech9_Myprice_Model_Observer
{
public function modifyPrice(Varien_Event_Observer $obs)
{
// Get the quote item
$item = $obs->getQuoteItem();
// Ensure we have the parent item, if it has one
$item = ( $item->getParentItem() ? $item->getParentItem() : $item );
// Load the custom price
$new_price = Mage::app()->getRequest()->getPost('custom_price');
Mage::log( $new_price);
$price = $new_price;
// Set the custom price
$item->setCustomPrice($price);
$item->setOriginalCustomPrice($price);
// Enable super mode on the product.
$item->getProduct()->setIsSuperMode(true);
}
}
Here Tech9 is the name of our package and Myprice is the name of our module.
We had to use our custom price during "add to cart" event. We prepared a separate module for it , if you like we can provide you with that package as well.
Problem I am having here is that people go to a Product page, set a quantity on how much they want of that product and add to cart (which than takes them to the cart page). Client wants the ability to go back to the shop/product page if they want to make further changes to that product (honestly this is strange, since they can do this on the cart page, but whatever). But when people go to update the quantity on the product page, instead of updating the quantity, it adds to the existing quantity for that product.
How to get it to update the existing quantity when the quantity has been submitted more than once on the product page? Is there a woocommerce loop that I can take advantage of here?
Thanks guys, I have dug through the plugin and coded the solution below:
add_action('woocommerce_add_to_cart_handler', 'update_product_in_cart', 11, 2);
function update_product_in_cart($p, $q) {
global $woocommerce;
$cartItem = $woocommerce->cart->cart_contents;
$currentProductId = $q->id;
$wCart = $woocommerce->cart->get_cart();
// If cart already exists, and product exists, than remove product, and add the new product to it.
if ($wCart)
{
$cart_item_keys = array_keys($wCart);
foreach($cart_item_keys as $key)
{
foreach($cartItem as $item)
{
$productItemId = $item['product_id'];
if ($productItemId == $currentProductId)
{
// If you want to empty the entire cart...
// $woocommerce->cart->empty_cart();
// If you want to remove just the product from the cart...
$woocommerce->cart->set_quantity($key, 0);
}
}
}
}
// This adds the product to the cart...
return $q;
}
This gets added to functions.php, and basically, if the product id exists in the cart, it removes the product and the return of $q adds in the new product info.
Works a charm!
I am currently building a module for an ecommerce website (Lemonstand). My shop sells both normal books and ebooks, and charge different rates of for shipping based on the subtotal of all items in the cart ($7 shipping cost for subtotal of less than $20, $14 shipping cost for between $20 and $50..etc). Currently the website just uses the subtotal of all items in the cart to determine which rate should be applied. The problem is, I want only the subtotal of normal books to be used for calculating shipping, because obviously ebooks don't need shipping.
Lemonstand platform has some built_in functions that I'm using to help with this. update_shipping_quote function is called just before shipping cost is calculated. It will be used to change the subtotal of cart items so that shipping cost can be calculated using the subtotal of non-ebooks instead.
Here is the API documentation for the function: https://v1.lemonstand.com/api/event/shop:onupdateshippingquote/
Here is the bit of code that's giving me trouble. I want to know if the value I get at the end ($non_ebook_subtotal) actually contains the value it's supposed to.
If anyone can come up with a better method for doing what I'm trying to do, please share.
//$params is an array containing things like individual item price
//Here I get the cart items and put them into var
public function
update_shipping_quote($shipping_option, $params) {
$cart_items = $params['cart_items'];
//find all products that are ebooks
foreach ($cart_items-> items as $item)
{
$product = $item->product;
if($product->product_type->code == 'ebook') {
$isEbook = true;
}
}
//add price of all ebooks into $ebook_subtotal
foreach ($cart_items as $item) {
$product = $item -> product;
if ($isEbook == true) {
$ebook_subtotal = $ebook_subtotal + total_price($product);
}
}
//Calculating the subtotal of only the non-ebook products
$non_ebook_subtotal = $params['total_price'] - $ebook_subtotal;
//This returns the non_ebook_subtotal to be used for calculating shipping cost
return array('total_price' => $non_ebook_subtotal);
}
Thanks
// get all variables needed
$totalprice = $params['total_price'];
$items = $params['cart_items'];
foreach ($items AS $item) {
// if is ebook
if ($item->product->product_type->code == 'ebook') {
// minus price of the item from total
$totalprice -= total_price($item->product);
}
}
return $totalprice;
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.