I am currently developing a webshop where i needed to do a separate price function. So far, with the help of woocommerce hooks, i had managed to manipulate the price in both the shopping cart and the checkout, this works without any problems at all. Hooks i have used woocommerce_cart_item_price, woocommerce_cart_item_subtotals, woocommerce_cart_subtotal and woocommerce_cart_total.
Now we come to my problem that i need to solve in the very near future. The price from my custom function is not included in the woocommerce order. So, is there a hook to manipulate the product prices in the order before the woocommerce creates the order?
I have looked at https://docs.woocommerce.com/wc-apidocs/hook-docs.html
but with no success.
Where does Woocommerce get the price from when it creates the order? The _price meta field, woocommerce_get_price hook, the cart or something else. I would be very grateful if someone could explain this to me. I find that woocommerce is not very consistent with where it's getting the price from.
Please ask questions if you don't understand my problem or my relative poor English. Thanks in advance.
I've use the woocommerce_get_price hook, when you change it, that changed price will be used for the cart to calculate the total (price * qty).
After order is placed, WooCommerce calculates the product based price on the total and qty, if you change one of the 2 values (total or qty) it will change the product price.
In other words, the price is dynamic after order has been created.
Edit:
Added method to change price
function change_price( $cart ) {
// Exit function if price is changed at backend
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart->get_cart() as $key => $item ) {
$item['data']->set_price( $custom_price );
}
}
add_action( 'woocommerce_before_calculate_totals', 'change_price', 10, 1);
Related
i know my question will not be answered, but i will ask.
i want subtotal to be calculated without considering sale price, that is, to consider the regular price, i did a lot of searching on the net, but i didn't get an answer.
i think i need to change the calculation method, but i don't know where to start.
echo wc_price( $product->get_regular_price() * $item['quantity'] );
it is not used on the order viewing page because if the order is today and the price changes tomorrow, the new price will be displayed, not the price at the time of placing the order.
If you want to access price at the time of order was placed,
you will have to access Order object for that.
// Get and Loop Over Order Items
foreach ( $order->get_items() as $item_id => $item ) {
$subtotal = $item->get_subtotal();
}
Use this links for reference,
https://www.businessbloomer.com/woocommerce-easily-get-order-info-total-items-etc-from-order-object/
How to get WooCommerce order details
I have found a plugin that creates customer specific pricing, but seems to be an external API call that seem to not be the solution I am looking for.
https://woocommerce.com/products/wisdm-customer-specific-pricing/
I was confused to how the cart works and how products are stored. But based on this post it showed me how to replace cart prices with customer ID and sku's being passed to the API.
I used this this ticket to start off my answer
So the big thing I needed to figure out is how to call the cart, loop through each product and grab it's product SKU then overwrite the price.
I added the following to my functions.php in my theme to change my cart to display the correct pricing based off of my customer API pricing. This does a loop through all my cart items then make a call to the API and returns a price for the specific customer and sku.
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
function add_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $key => $value ) {
$response = get_api_response($value['data']->get_sku(), $customer_id);
$custom_price = $response->price;
$value['data']->set_price($custom_price);
}
}
I have a plugin which applies discounts based on the category of the product. I'm using the filters below to add text to the order table in the cart:
add_filter('woocommerce_cart_product_subtotal', array($this,'change_product_subtotal'), 10, 4);
add_filter( 'woocommerce_cart_product_price', array($this,'change_product_price'), 10, 2);
add_filter( 'woocommerce_cart_item_name', array($this,'change_product_name'), 10, 2);
And this action to change the total price of the order/cart.
add_action( 'woocommerce_after_calculate_totals', array($this,'ca_change_cart_total'), 10, 1 );
The total price of the order pulls through to the checkout, as do the modified product fields. However when the order has been placed, the filters no longer have any effect (however the total order price is correct). My question is: what are the hooks I need to use to add the text present in the cart, to the placed order screen OR what is an alternative approach that will achieve the same outcome.I have provided screenshots showing the stages of the order. Thanks for any contributions.
For anyone having the same issue. I found an alternative method to using filters. Upon order creation loop through all the items in the order and change the totals. This has the advantage of effectively changing the unit price of the each product so in the WooCommerce admin area, if you are needing to issue a refund, the correct unit price is displayed. I have shown my code below, obviously replace 999 with the relevant total price for each product (ie unit price * quantity) using whatever custom logic your use case requires.
add_action('woocommerce_checkout_create_order', 'on_checkout_create_order', 20, 2);
function on_checkout_create_order( $order, $data ) {
foreach( $order->get_items() as $item_id => $line_item ){
$order->items[$item_id]->set_subtotal(999);
$order->items[$item_id]->set_total(999);
}
}
I have a custom product built with Gravity forms conditional logic. Weights are added in a separate plugin to be used for shipping. Shipping is multi-carrier. The problem we are having is that the weights are added at the cart level, but the live rates shipping plugins we have tried checks for weights coming from the product rather than at the cart. Is there a way to programmatically add the weights to the product before it is added to the cart?
Our code to add the weights to the product is:
add_action( 'woocommerce_add_to_cart', 'kj_after_add_cart_item', 10, 3 );
function kj_after_add_cart_item( $cart_item_key, $product_id, $quantity ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach( WC()->cart->get_cart() as $cart_item ){
if ( isset($cart_item['weight']['new']) ) {
$cart_item['data']->set_weight($cart_item['weight']['new']);
}
}
}
This is the plugin developers response on how the weight is found:
"We retrieve the weight from WooCommerce Product object. Ex: $product->get_weight()
When WooCommerce calculate_shipping() is triggered the plugin gets the Cart/Checkout Packages from which we get the Product Object."
Is there a way to add the weights to the product where it can be found at $product->get_weight() so we can use a live rates shipping plugin?
Thanks for any help on this.
I am creating an eCommerce store for a relative's business. He has products that the user must personalize on the website. I am coding a separate page that will allow the user to do this, that will link back to the store and add the item to the cart when they are done.
I found a solution to add each product to the cart separately, instead of adding to the quantity (since each product added has been personalized), and a solution to change the price of items in the cart.
WooCommerce: Add product to cart with price override?
https://businessbloomer.com/woocommerce-display-separate-cart-items-product-quantity-1/
The problem is that all the items are changed, not just the last one added.
For example: User designs a ballpoint pen with her name on it. The price is $4. The user then designs a gel pen with her name. The cart will show two separate pens with an increased calculated price, but the price will increase for all pens, not just the last one added. I need to find a way to set the price for the last item added, based on the price sent from the product building page. So far, nothing I've tried has worked.
Variable products won't work for this site.
//To display a product separately every time it is added
function bbloomer_split_product_individual_cart_items( $cart_item_data, $product_id ){
$unique_cart_item_key = uniqid();
$cart_item_data['unique_key'] = $unique_cart_item_key;
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data','bbloomer_split_product_individual_cart_items', 10, 2 );
add_filter( 'woocommerce_is_sold_individually', '__return_true' );
//To change the item price programmatically. Changes all items with the same ID
//I need it to change only the last one added.
//Set to retrieve new price from the customizing page
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
/**
* #param $cart_obj
*/
function add_custom_price($cart_obj ) {
ob_start();
include 'createbb.php';
global $custom_price;
$target_product_id = 17;
// This is necessary for WC 3.0+
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
foreach ( $cart_obj->get_cart() as $key => $value ) {
if ($value['product_id'] == $target_product_id) {
$value['data']->set_price($custom_price);
}
}
ob_end_clean();
}
The type of functionality you are looking for is actually so common that it has a name "Product Options" (this is different to variations). This feature allows you to add configurable add-on's to the price of a product through a design on the edit product page. In a lot of eCommerce platforms like OpenCart you have this sort of functionality built in for free, however Automattic opted to keep it as a separate bolt on which they charge for:
https://woocommerce.com/products/product-add-ons/
Before you say it yes it is annoying that they charge for it, really this is such a common thing for people to request you can tell that it was a calculated decision to monetise it. And yes it is still very possible to program everything bespoke, but you are inevitably re-inventing the wheel for no reason other than to avoid paying for the feature (there are free versions of the plugin above that others have made, google is your friend).
Consider something, what if Automattic change their hooks in the future? you'll have to modify your code, assuming you find out before it borks the site. What if you wish to change options, or you need someone else to change them and you are not around?
If you weigh things up, you'll find the best option in the end is either to grab the official plug-in, or use one of the free alternatives. Trust me I am doing you a favour.
Koda