I have a pretty weird issue, I hope someone can help me with this.
Here are the major config settings that influence my problem:
Catalog prices in admin panel are shown including tax
Catalog prices in frontend are shown including tax
Items in shopping cart are shown excluding tax (so it's displayed separately near the subtotal).
Everything is working fine so far. The problem comes in a custom ajax mini cart module. I grab the collection of items from the cart, but, since I'm getting the price from the shopping cart item, I get it without tax.
Here is some code to exemplify what I mean. I will assume a 20% tax and a product that has the admin price (including tax) set to 120$, an option that costs 60$ (also including tax). Excluding tax these would be 100$ and 50$. I want to get the price + option + tax => 180$
$quote = Mage::getSingleton('checkout/session')->getQuote();
$items = $quote->getAllVisibleItems();
foreach ($items as $item) {
echo $item->getPrice(); // 150$ - price excluding tax
echo $item->getPriceInclTax(); // 150$ - price excluding tax
echo $item->getProduct()->getPrice(); // 120$ price including tax, BUT without the customer selected options.
}
PS: The custom option I am talking about is user selected, for example an install checkbox that adds +50$ to the price of the product.
- Get products id, name, price, quantity, etc. present in your cart.
- Get number of items in cart and total quantity in cart.
- Get base total price and grand total price of items in cart.
Get all items information in cart
// $items = Mage::getModel('checkout/cart')->getQuote()->getAllItems();
$items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems();
foreach($items as $item) {
echo 'ID: '.$item->getProductId().'<br />';
echo 'Name: '.$item->getName().'<br />';
echo 'Sku: '.$item->getSku().'<br />';
echo 'Quantity: '.$item->getQty().'<br />';
echo 'Price: '.$item->getPrice().'<br />';
echo "<br />";
}
Get total items and total quantity in cart
$totalItems = Mage::getModel('checkout/cart')->getQuote()->getItemsCount();
$totalQuantity = Mage::getModel('checkout/cart')->getQuote()->getItemsQty();
Get subtotal and grand total price of cart
$subTotal = Mage::getModel('checkout/cart')->getQuote()->getSubtotal();
$grandTotal = Mage::getModel('checkout/cart')->getQuote()->getGrandTotal();
Have you tried:
$product->getFinalPrice();
// or this?
$product->getPriceModel()->getFinalPrice($qty, $product);
what is the ouput of $item->getOptions()?
Have you tried $item->getData('price')?
How do you apply your custom options? What is the ouput of $item->debug()? Maybe you can find what you need there.
Regards
Simon
I didn't find a solution to my exact problem, but I changed the settings to mimic this exact functionality, and the problem I encountered was no longer there.
First of all, I removed all the taxes on the site, and told magento all the prices are excluding tax (even though they are including tax).
The tax reduction is now made through a promotion applied on a custom group, so for
$tax = 20; // percent
I add a reduction of
(1 - (1 / ($tax / 100 + 1)))*100
// for 20% tax => 16.6667% reduction
// for 24% tax => 19.3548% reduction
with 4 decimals (that's as much as magento accepts). It may have an error of 1 cent from time to time - so if this is not an issue, go for it!
Now the prices all over the website will be shown exactly for the product (because the promotion is applied per cart, not per product).
You can try This :
$grandTotal = $this->helper('checkout/cart')->getQuote()->getGrandTotal();
echo $text .= $this->__(' Total: %s', $this->helper('core')->formatPrice($grandTotal, false));
show the quantity of a cart in my header
if ($parentBlock = $this->getParentBlock()) {
$count = $this->helper('checkout/cart')->getSummaryCount();
if( $count == 1 ) {
echo $text = $this->__('My Cart (%s item)', $count);
} elseif( $count > 0 ) {
echo $text = $this->__('My Cart (%s items)', $count);
} else {
echo $text = $this->__('My Cart (0 items)');
}
}
show the total price of a cart in my header
$grandTotal = $this->helper('checkout/cart')->getQuote()->getGrandTotal();
echo $text .= $this->__(' Total: %s', $this->helper('core')->formatPrice($grandTotal, false));
Related
From my understanding of how woocommerce_coupon_get_discount_amount works. The discount is calculated as to how much it would discount each item in the cart. For example, if you had 4 items in the cart at $10, and you were to discount one item to be free. Then you would return $2.50 to each product in the cart. Thus discounting one of the products by 100%.
However, let's say that you had a product in the cart that was $1, then instead of discounting $10, the discount applied would be $8.50. Making the discount incorrect.
For this above example the coupon would be calculated as so:
add_filter('woocommerce_coupon_get_discount_amount', 'mb_wcchpi_cpn_disc', 10, 5);
function mb_wcchpi_cpn_disc($discount, $discounting_amount, $cart_item, $single, $coupon)
{
//IF CUSTOM COUPON TYPE
if ($coupon->type == 'most_expensive_coupon') {
//Gets the most expensive item in the cart
$mostExpensiveItem = FindMaxPricedItem($multiple_products);
//Get the price of the most expensive item in the cart
$maxPrice = $mostExpensiveItem['price'];
//GET THE COUPON DISCOUNT AMOUNT
$amt = floatval($coupon->amount);
//GET THE DISCOUNT AMOUNT
$discount = ($amt / 100) * $maxPrice;
//GET THE ITEMS IN THE CART
$itemCount = WC()->cart->cart_contents_count;
//DISTRIBUTE EQUALLY ACROSS ALL ITEMS IN CART
$discount = $discount / $itemCount;
}
return $discount;
}
How would one handle the edge case of having an item in the cart that is less than the discount amount? Is there a different action than woocommerce_coupon_get_discount_amount to be used for applying a coupon to the cart total instead of per item? Is there a different formula I should be using to come up with the discount?
I am using the cart widget from WooCommerce -> mini-cart.php
I am adding products to it via AJAX and added some elements already to it myself. Standard it shows the subtotal price in the cart but I want to show the shipping costs after it and after that the total price (subtotal + shipping).
So the cart will look like this:
- Products in cart
- Subtotal
- Shipping costs
- Total price (shipping + subtotal)
I have added the total price with this code:
<p><?php echo WC()->cart->get_cart_total(); ?></p>
But this echo's the same price as the subtotal because the shipping isn't added to it. Can someone help me to add the shipping costs to it. Some hook or code.
To get and display the chosen shipping method label (and other related data, if needed) in cart page (or in checkout page):
foreach( WC()->session->get('shipping_for_package_0')['rates'] as $method_id => $rate ){
if( WC()->session->get('chosen_shipping_methods')[0] == $method_id ){
$rate_label = $rate->label; // The shipping method label name
$rate_cost_excl_tax = floatval($rate->cost); // The cost excluding tax
// The taxes cost
$rate_taxes = 0;
foreach ($rate->taxes as $rate_tax)
$rate_taxes += floatval($rate_tax);
// The cost including tax
$rate_cost_incl_tax = $rate_cost_excl_tax + $rate_taxes;
echo '<p class="shipping-total">
<strong class="label">'.$rate_label.': </strong>
<span class="totals">'. WC()->cart->get_cart_shipping_total() .'</span>
</p>';
break;
}
}
I have set up a Woocommerce shop and wish to set up a specific discount on all products based on multiples of 12 (a box). I've tried many discount plugins but haven't found what I am looking for.
For example, if I order 12 of product X, I get a 10% discount. If I order 15 of product X, I get a 10% discount on the first 12, and the last three are full price. If I order 24, then that 10% discount applies to all 24 of product X.
The closest I have found is this: Discount for Certain Category Based on Total Number of Products
But this is applied as a discount (actually a negative fee) at the end, and I'd like to display the discount in the cart next to the product, like normal discounts.
I also need this discount to be disabled if a product is already on sale.
Thanks.
This code will not work in Woocommerce 3+…
See: Cart item discount based on quantity in Woocommerce 3:
Yes this is also possible, making a custom calculation for each cart item and replacing individually their price (matching your conditions and calculations), using a custom function hooked in woocommerce_before_calculate_totals action hook.
This is the code:
add_action( 'woocommerce_before_calculate_totals', 'custom_discounted_cart_item_price', 10, 1 );
function custom_discounted_cart_item_price( $cart_object ) {
$discount_applied = false;
// Set Here your targeted quantity discount
$t_qty = 12;
// Iterating through each item in cart
foreach ( $cart_object->get_cart() as $item_values ) {
## Get cart item data
$item_id = $item_values['data']->id; // Product ID
$item_qty = $item_values['quantity']; // Item quantity
$original_price = $item_values['data']->price; // Product original price
// Getting the object
$product = new WC_Product( $item_id );
// CALCULATION FOR EACH ITEM
// when quantity is up to the targetted quantity and product is not on sale
if( $item_qty >= $t_qty && !$product->is_on_sale() ){
for($j = $t_qty, $loops = 0; $j <= $item_qty; $j += $t_qty, $loops++);
$modulo_qty = $item_qty % $t_qty; // The remaining non discounted items
$item_discounted_price = $original_price * 0.9; // Discount of 10 percent
$total_discounted_items_price = $loops * $t_qty * $item_discounted_price;
$total_normal_items_price = $modulo_qty * $original_price;
// Calculating the new item price
$new_item_price = ($total_discounted_items_price + $total_normal_items_price) / $item_qty;
// Setting the new price item
$item_values['data']->price = $new_item_price;
$discount_applied = true;
}
}
// Optionally display a message for that discount
if ( $discount_applied )
wc_add_notice( __( 'A quantity discount has been applied on some cart items.', 'my_theme_slug' ), 'success' );
}
This make exactly the discount that you are expecting separately for each item in cart (based on it's quantity) and not for items that are in sale. But you will not get any label (text) indicating a discount in the line items of cart.
Optionally I display a notice when a discount is applied to some cart items…
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
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 have this code on my products view.phtml file: I am getting a shipping estimate and basing the lowest cost to a UK address and rendering this on the products page. Rather than having a full blown shipping estimator on the pages.
<?php
if($_product->isSaleable())
{
$quote = Mage::getModel('sales/quote');
$quote->getShippingAddress()->setCountryId('GB');
$quote->addProduct($_product);
$quote->getShippingAddress()->collectTotals();
$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->getShippingAddress()->collectShippingRates();
$rates = $quote->getShippingAddress()->getShippingRatesCollection();
$minPrice = PHP_INT_MAX;
foreach ($rates as $rate) {
$minPrice = min($minPrice, $rate->getPrice());
}
if ($minPrice == 0) {
echo ('This item qualifies for FREE shipping');
}
elseif ($minPrice < PHP_INT_MAX) {
echo ('Shipping to UK from £' . money_format('%i', $rate->getPrice()) . "\n");
}
}
?>
Which works fine for simple products. however on configurable products, it always displays free shipping! How can get around this?
This is just a guess, but a configurable product is just a container to organize a bunch of simple products. When you add a product to the cart (for real), there is a simple product in the cart in addition to the configurable one. I'm guessing that this second product provides the weight and information for shipping, etc.
That would imply that, to get your shipping estimate, you'll need to specify one of the simple products underneath the configurable (either directly, or by passing some options and pretending to have "selected" a product) in order to see your shipping estimates.